diff options
Diffstat (limited to 'libs/surfaceflinger')
-rw-r--r-- | libs/surfaceflinger/Android.mk | 1 | ||||
-rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 46 | ||||
-rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardware.h | 10 | ||||
-rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp | 20 | ||||
-rw-r--r-- | libs/surfaceflinger/GPUHardware/GPUHardware.cpp | 608 | ||||
-rw-r--r-- | libs/surfaceflinger/GPUHardware/GPUHardware.h | 77 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 33 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.cpp | 37 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.h | 14 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBlur.cpp | 10 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.cpp | 52 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.h | 6 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerDim.cpp | 4 | ||||
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.cpp | 79 | ||||
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.h | 9 | ||||
-rw-r--r-- | libs/surfaceflinger/VRamHeap.cpp | 81 | ||||
-rw-r--r-- | libs/surfaceflinger/VRamHeap.h | 22 |
17 files changed, 588 insertions, 521 deletions
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 7741456..d14cebf 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -31,6 +31,7 @@ ifeq ($(TARGET_SIMULATOR),true) endif LOCAL_SHARED_LIBRARIES := \ + libhardware \ libutils \ libcutils \ libui \ diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 5dd9446..cd72179 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -19,6 +19,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <math.h> #include <GLES/egl.h> @@ -27,7 +28,9 @@ #include <ui/EGLDisplaySurface.h> #include "DisplayHardware/DisplayHardware.h" -#include "ui/BlitHardware.h" + +#include <hardware/copybit.h> +#include <hardware/overlay.h> using namespace android; @@ -91,19 +94,13 @@ DisplayHardware::~DisplayHardware() fini(); } -float DisplayHardware::getDpiX() const { return mDpiX; } -float DisplayHardware::getDpiY() const { return mDpiY; } -float DisplayHardware::getRefreshRate() const { return mRefreshRate; } - -int DisplayHardware::getWidth() const { - return mWidth; -} -int DisplayHardware::getHeight() const { - return mHeight; -} -PixelFormat DisplayHardware::getFormat() const { - return mFormat; -} +float DisplayHardware::getDpiX() const { return mDpiX; } +float DisplayHardware::getDpiY() const { return mDpiY; } +float DisplayHardware::getDensity() const { return mDensity; } +float DisplayHardware::getRefreshRate() const { return mRefreshRate; } +int DisplayHardware::getWidth() const { return mWidth; } +int DisplayHardware::getHeight() const { return mHeight; } +PixelFormat DisplayHardware::getFormat() const { return mFormat; } void DisplayHardware::init(uint32_t dpy) { @@ -195,6 +192,12 @@ void DisplayHardware::init(uint32_t dpy) mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING; } mRefreshRate = 60.f; // TODO: get the real refresh rate + + // compute a "density" automatically as a scale factor from 160 dpi + // TODO: this value should be calculated a compile time based on the + // board. + mDensity = floorf((mDpiX>mDpiY ? mDpiX : mDpiY)*0.1f + 0.5f) * (10.0f/160.0f); + LOGI("density = %f", mDensity); /* * Create our OpenGL ES context @@ -237,8 +240,18 @@ void DisplayHardware::init(uint32_t dpy) mSurface = surface; mContext = context; mFormat = GGL_PIXEL_FORMAT_RGB_565; + + hw_module_t const* module; - mBlitEngine = copybit_init(); + mBlitEngine = NULL; + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { + copybit_open(module, &mBlitEngine); + } + + mOverlayEngine = NULL; + if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { + overlay_open(module, &mOverlayEngine); + } } /* @@ -252,7 +265,8 @@ void DisplayHardware::fini() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(mDisplay); - copybit_term(mBlitEngine); + copybit_close(mBlitEngine); + overlay_close(mOverlayEngine); } void DisplayHardware::releaseScreen() const diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index 299e236..de4a2cc 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -26,6 +26,8 @@ #include "DisplayHardware/DisplayHardwareBase.h" +struct overlay_device_t; +struct copybit_device_t; struct copybit_image_t; struct copybit_t; @@ -64,6 +66,7 @@ public: float getDpiX() const; float getDpiY() const; float getRefreshRate() const; + float getDensity() const; int getWidth() const; int getHeight() const; PixelFormat getFormat() const; @@ -74,7 +77,8 @@ public: void getDisplaySurface(copybit_image_t* img) const; void getDisplaySurface(GGLSurface* fb) const; EGLDisplay getEGLDisplay() const { return mDisplay; } - copybit_t* getBlitEngine() const { return mBlitEngine; } + copybit_device_t* getBlitEngine() const { return mBlitEngine; } + overlay_device_t* getOverlayEngine() const { return mOverlayEngine; } Rect bounds() const { return Rect(mWidth, mHeight); @@ -91,13 +95,15 @@ private: float mDpiX; float mDpiY; float mRefreshRate; + float mDensity; int mWidth; int mHeight; PixelFormat mFormat; uint32_t mFlags; mutable Region mDirty; sp<EGLDisplaySurface> mDisplaySurface; - copybit_t* mBlitEngine; + copybit_device_t* mBlitEngine; + overlay_device_t* mOverlayEngine; }; }; // namespace android diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index 90f6287..f75e5c2 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -49,8 +49,10 @@ // ---------------------------------------------------------------------------- namespace android { -static char const * const kSleepFileName = "/sys/android_power/wait_for_fb_sleep"; -static char const * const kWakeFileName = "/sys/android_power/wait_for_fb_wake"; +static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep"; +static char const * kWakeFileName = "/sys/power/wait_for_fb_wake"; +static char const * const kOldSleepFileName = "/sys/android_power/wait_for_fb_sleep"; +static char const * const kOldWakeFileName = "/sys/android_power/wait_for_fb_wake"; // This dir exists if the framebuffer console is present, either built into // the kernel or loaded as a module. @@ -123,16 +125,22 @@ status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const status_t DisplayHardwareBase::DisplayEventThread::readyToRun() { if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) { - LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName); - return NO_INIT; + if (access(kOldSleepFileName, R_OK) || access(kOldWakeFileName, R_OK)) { + LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName); + return NO_INIT; + } + kSleepFileName = kOldSleepFileName; + kWakeFileName = kOldWakeFileName; } return NO_ERROR; } status_t DisplayHardwareBase::DisplayEventThread::initCheck() const { - return (access(kSleepFileName, R_OK) == 0 && - access(kWakeFileName, R_OK) == 0 && + return (((access(kSleepFileName, R_OK) == 0 && + access(kWakeFileName, R_OK) == 0) || + (access(kOldSleepFileName, R_OK) == 0 && + access(kOldWakeFileName, R_OK) == 0)) && access(kFbconSysDir, F_OK) != 0) ? NO_ERROR : NO_INIT; } 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(); } // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.h b/libs/surfaceflinger/GPUHardware/GPUHardware.h index 9a78b99..3354528 100644 --- a/libs/surfaceflinger/GPUHardware/GPUHardware.h +++ b/libs/surfaceflinger/GPUHardware/GPUHardware.h @@ -22,92 +22,39 @@ #include <utils/RefBase.h> #include <utils/threads.h> +#include <utils/KeyedVector.h> + +#include <ui/ISurfaceComposer.h> namespace android { // --------------------------------------------------------------------------- -class GPUHardwareInterface : public RefBase +class IGPUCallback; + +class GPUHardwareInterface : public virtual RefBase { public: virtual void revoke(int pid) = 0; virtual sp<MemoryDealer> request(int pid) = 0; - virtual status_t request(const sp<IGPUCallback>& callback, + virtual status_t request(int pid, const sp<IGPUCallback>& callback, ISurfaceComposer::gpu_info_t* gpu) = 0; virtual status_t friendlyRevoke() = 0; - virtual void unconditionalRevoke() = 0; // used for debugging only... virtual sp<SimpleBestFitAllocator> getAllocator() const = 0; virtual pid_t getOwner() const = 0; + virtual void unconditionalRevoke() = 0; }; // --------------------------------------------------------------------------- -class IMemory; -class MemoryHeapPmem; -class PMemHeap; - -class GPUHardware : public GPUHardwareInterface -{ +class GPUFactory +{ public: - GPUHardware(); - virtual ~GPUHardware(); - - virtual void revoke(int pid); - virtual sp<MemoryDealer> request(int pid); - virtual status_t request(const sp<IGPUCallback>& callback, - ISurfaceComposer::gpu_info_t* gpu); - - virtual status_t friendlyRevoke(); - virtual void unconditionalRevoke(); - - // used for debugging only... - virtual sp<SimpleBestFitAllocator> getAllocator() const; - virtual pid_t getOwner() const { return mOwner; } - -private: - enum { - NO_OWNER = -1, - SURFACE_FAILED = -2 - }; - - void requestLocked(); - void releaseLocked(bool dispose = false); - void takeBackGPULocked(); - - class GPUPart - { - public: - bool surface; - size_t reserved; - GPUPart(); - ~GPUPart(); - const sp<PMemHeapInterface>& getHeap() const; - const sp<MemoryHeapPmem>& getClientHeap() const; - bool isValid() const; - void clear(); - void set(const sp<PMemHeapInterface>& heap); - bool promote(); - sp<IMemory> map(bool clear = false); - void release(bool dispose); - private: - sp<PMemHeapInterface> mHeap; - wp<PMemHeapInterface> mHeapWeak; - sp<MemoryHeapPmem> mClientHeap; - }; - - mutable Mutex mLock; - GPUPart mHeap0; // SMI - GPUPart mHeap1; // EBI1 - GPUPart mHeapR; - sp<MemoryDealer> mAllocator; - pid_t mOwner; - sp<IGPUCallback> mCallback; - wp<SimpleBestFitAllocator> mAllocatorDebug; - - Condition mCondition; + // the gpu factory + static sp<GPUHardwareInterface> getGPU(); }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 4f6bae1..8ba0851 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -92,26 +92,29 @@ status_t Layer::setBuffers( Client* client, status_t err = getPixelFormatInfo(format, &info); if (err) return err; - // TODO: if eHardware is explicitely requested, we should fail + // TODO: if eHardware is explicitly requested, we should fail // on systems where we can't allocate memory that can be used with // DMA engines for instance. + + // FIXME: we always ask for hardware for now (this should come from copybit) + flags |= ISurfaceComposer::eHardware; - int memory_type = NATIVE_MEMORY_TYPE_PMEM; + const uint32_t memory_flags = flags & + (ISurfaceComposer::eGPU | + ISurfaceComposer::eHardware | + ISurfaceComposer::eSecure); // pixel-alignment. the final alignment may be bigger because // we always force a 4-byte aligned bpr. uint32_t alignment = 1; - const uint32_t mask = ISurfaceComposer::eGPU | ISurfaceComposer::eSecure; - if ((flags & mask) == ISurfaceComposer::eGPU) { - // don't grant GPU memory if GPU is disabled - char value[PROPERTY_VALUE_MAX]; - property_get("debug.egl.hw", value, "1"); - if (atoi(value) != 0) { - flags |= ISurfaceComposer::eHardware; - memory_type = NATIVE_MEMORY_TYPE_GPU; - // TODO: this value should come from the h/w - alignment = 8; + if (flags & ISurfaceComposer::eGPU) { + // FIXME: this value should come from the h/w + alignment = 8; + // FIXME: this is msm7201A specific, as its GPU only supports + // BGRA_8888. + if (format == PIXEL_FORMAT_RGBA_8888) { + format = PIXEL_FORMAT_BGRA_8888; } } @@ -119,7 +122,7 @@ status_t Layer::setBuffers( Client* client, mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; sp<MemoryDealer> allocators[2]; for (int i=0 ; i<2 ; i++) { - allocators[i] = client->createAllocator(memory_type); + allocators[i] = client->createAllocator(memory_flags); if (allocators[i] == 0) return NO_MEMORY; mBuffers[i].init(allocators[i]); @@ -133,7 +136,7 @@ status_t Layer::setBuffers( Client* client, mSurface = new Surface(clientIndex(), allocators[0]->getMemoryHeap(), allocators[1]->getMemoryHeap(), - memory_type, mIdentity); + mIdentity); return NO_ERROR; } @@ -180,7 +183,7 @@ void Layer::onDraw(const Region& clip) const front.getBitmapSurface(&src); copybit_rect_t srect = { 0, 0, t.width, t.height }; - copybit_t* copybit = mFlinger->getBlitEngine(); + copybit_device_t* copybit = mFlinger->getBlitEngine(); copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation()); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); copybit->set_parameter(copybit, COPYBIT_DITHER, diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 17c9f42..af353e2 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -30,7 +30,7 @@ #include "DisplayHardware/DisplayHardware.h" -// We don't honor the premultipliad alpha flags, which means that +// We don't honor the premultiplied alpha flags, which means that // premultiplied surface may be composed using a non-premultiplied // equation. We do this because it may be a lot faster on some hardware // The correct value is HONOR_PREMULTIPLIED_ALPHA = 1 @@ -256,7 +256,7 @@ void LayerBase::validateVisibility(const Transform& planeTransform) // see if we can/should use 2D h/w with the new configuration mCanUseCopyBit = false; - copybit_t* copybit = mFlinger->getBlitEngine(); + copybit_device_t* copybit = mFlinger->getBlitEngine(); if (copybit) { const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG); const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS); @@ -413,7 +413,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, // premultiplied alpha. // If the texture doesn't have an alpha channel we can - // use REPLACE and switch to non premultiplied-alpha + // use REPLACE and switch to non premultiplied alpha // blending (SRCA/ONE_MINUS_SRCA). GLenum env, src; @@ -431,11 +431,11 @@ void LayerBase::drawWithOpenGL(const Region& clip, glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); } else { glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor4x(0x10000, 0x10000, 0x10000, 0x10000); if (needsBlending()) { GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); - glColor4x(0x10000, 0x10000, 0x10000, 0x10000); } else { glDisable(GL_BLEND); } @@ -463,7 +463,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, glMatrixMode(GL_TEXTURE); glLoadIdentity(); if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { - // find the smalest power-of-two that will accomodate our surface + // find the smallest power-of-two that will accommodate our surface GLuint tw = 1 << (31 - clz(t.width)); GLuint th = 1 << (31 - clz(t.height)); if (tw < t.width) tw <<= 1; @@ -556,7 +556,7 @@ void LayerBase::loadTexture(const Region& dirty, GLuint texture_w = tw; GLuint texture_h = th; if (!(flags & DisplayHardware::NPOT_EXTENSION)) { - // find the smalest power-of-two that will accomodate our surface + // find the smallest power-of-two that will accommodate our surface texture_w = 1 << (31 - clz(t.width)); texture_h = 1 << (31 - clz(t.height)); if (texture_w < t.width) texture_w <<= 1; @@ -582,6 +582,8 @@ void LayerBase::loadTexture(const Region& dirty, glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, t.data); + } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) { + // TODO: add GL_BGRA extension } else { // oops, we don't handle this format, try the regular path goto regular; @@ -592,7 +594,7 @@ void LayerBase::loadTexture(const Region& dirty, regular: Rect bounds(dirty.bounds()); GLvoid* data = 0; - if (texture_w!=textureWidth || texture_w!=textureHeight) { + if (texture_w!=textureWidth || texture_h!=textureHeight) { // texture size changed, we need to create a new one if (!textureWidth || !textureHeight) { @@ -606,31 +608,36 @@ regular: bounds.set(Rect(tw, th)); } } - + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, tw, th, 0, + GL_RGB, texture_w, texture_h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, tw, th, 0, + GL_RGBA, texture_w, texture_h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, tw, th, 0, + GL_RGBA, texture_w, texture_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { // just show the Y plane of YUV buffers data = t.data; glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, tw, th, 0, + GL_LUMINANCE, texture_w, texture_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + // oops, we don't handle this format! + LOGE("layer %p, texture=%d, using format %d, which is not " + "supported by the GL", this, textureName, t.format); + textureName = -1; } - textureWidth = tw; - textureHeight = th; + textureWidth = texture_w; + textureHeight = texture_h; } - if (!data) { + if (!data && textureName>=0) { if (t.format == GGL_PIXEL_FORMAT_RGB_565) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 10c1bc1..b3f3771 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -23,6 +23,8 @@ #include <private/ui/LayerState.h> #include <ui/Region.h> +#include <ui/Overlay.h> + #include <pixelflinger/pixelflinger.h> #include "Transform.h" @@ -223,16 +225,14 @@ public: Surface(SurfaceID id, int identity) { mParams.token = id; mParams.identity = identity; - mParams.type = 0; } Surface(SurfaceID id, const sp<IMemoryHeap>& heap0, const sp<IMemoryHeap>& heap1, - int memory_type, int identity) + int identity) { mParams.token = id; mParams.identity = identity; - mParams.type = memory_type; mParams.heap[0] = heap0; mParams.heap[1] = heap1; } @@ -240,8 +240,8 @@ public: // TODO: We now have a point here were we can clean-up the // client's mess. // This is also where surface id should be recycled. - //LOGD("Surface %d, heaps={%p, %p}, type=%d destroyed", - // mId, mHeap[0].get(), mHeap[1].get(), mMemoryType); + //LOGD("Surface %d, heaps={%p, %p} destroyed", + // mId, mHeap[0].get(), mHeap[1].get()); } virtual void getSurfaceData( @@ -254,6 +254,10 @@ public: { return INVALID_OPERATION; } virtual void postBuffer(ssize_t offset) { } virtual void unregisterBuffers() { }; + virtual sp<Overlay> createOverlay( + uint32_t w, uint32_t h, int32_t format) { + return NULL; + }; private: ISurfaceFlingerClient::surface_data_t mParams; diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index 192ceda..e3ae7fb 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -145,11 +145,13 @@ void LayerBlur::onDraw(const Region& clip) const mRefreshCache = false; mAutoRefreshPending = false; - uint16_t* const pixels = (uint16_t*)malloc(w*h*2); + // allocate enough memory for 4-bytes (2 pixels) aligned data + const int32_t s = (w + 1) & ~1; + uint16_t* const pixels = (uint16_t*)malloc(s*h*2); - // this reads the frame-buffer, so a h/w GL would have to + // This reads the frame-buffer, so a h/w GL would have to // finish() its rendering first. we don't want to do that - // too often. + // too often. Read data is 4-bytes aligned. glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); // blur that texture. @@ -157,7 +159,7 @@ void LayerBlur::onDraw(const Region& clip) const bl.version = sizeof(GGLSurface); bl.width = w; bl.height = h; - bl.stride = w; + bl.stride = s; bl.format = GGL_PIXEL_FORMAT_RGB_565; bl.data = (GGLubyte*)pixels; blurFilter(&bl, 8, 2); diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index d871fc3..3861e68 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -104,7 +104,7 @@ void LayerBuffer::onDraw(const Region& clip) const * the requested scale factor, in which case we perform the scaling * in several passes. */ - copybit_t* copybit = mFlinger->getBlitEngine(); + copybit_device_t* copybit = mFlinger->getBlitEngine(); const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); @@ -123,7 +123,7 @@ void LayerBuffer::onDraw(const Region& clip) const if (UNLIKELY(mTemporaryDealer == 0)) { // allocate a memory-dealer for this the first time mTemporaryDealer = mFlinger->getSurfaceHeapManager() - ->createHeap(NATIVE_MEMORY_TYPE_PMEM); + ->createHeap(ISurfaceComposer::eHardware); mTempBitmap.init(mTemporaryDealer); } @@ -230,7 +230,18 @@ sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride, PixelFormat format, const sp<IMemoryHeap>& memoryHeap) { - status_t err = (memoryHeap!=0 && memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT; + if (memoryHeap == NULL) { + // this is allowed, but in this case, it is illegal to receive + // postBuffer(). The surface just erases the framebuffer with + // fully transparent pixels. + mHeap.clear(); + mWidth = w; + mHeight = h; + mNeedsBlending = false; + return NO_ERROR; + } + + status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT; if (err != NO_ERROR) return err; @@ -281,6 +292,32 @@ void LayerBuffer::unregisterBuffers() invalidateLocked(); } +sp<Overlay> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t format) +{ + sp<Overlay> result; + Mutex::Autolock _l(mLock); + if (mHeap != 0 || mBuffer != 0) { + // we're a push surface. error. + return result; + } + + overlay_device_t* overlay_dev = mFlinger->getOverlayEngine(); + if (overlay_dev == NULL) { + // overlays not supported + return result; + } + + overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format); + if (overlay == NULL) { + // couldn't create the overlay (no memory? no more overlays?) + return result; + } + + /* TODO: implement the real stuff here */ + + return result; +} + sp<LayerBuffer::Buffer> LayerBuffer::getBuffer() const { Mutex::Autolock _l(mLock); @@ -330,6 +367,15 @@ void LayerBuffer::SurfaceBuffer::unregisterBuffers() owner->unregisterBuffers(); } +sp<Overlay> LayerBuffer::SurfaceBuffer::createOverlay( + uint32_t w, uint32_t h, int32_t format) { + sp<Overlay> result; + LayerBuffer* owner(getOwner()); + if (owner) + result = owner->createOverlay(w, h, format); + return result; +} + void LayerBuffer::SurfaceBuffer::disown() { Mutex::Autolock _l(mLock); diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index ef473dd..3e616f2 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -33,6 +33,7 @@ namespace android { class MemoryDealer; class Region; +class Overlay; class LayerBuffer : public LayerBaseClient { @@ -56,6 +57,7 @@ public: PixelFormat format, const sp<IMemoryHeap>& heap); void postBuffer(ssize_t offset); void unregisterBuffers(); + sp<Overlay> createOverlay(uint32_t w, uint32_t h, int32_t format); void invalidate(); void invalidateLocked(); @@ -107,7 +109,9 @@ private: PixelFormat format, const sp<IMemoryHeap>& heap); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); - void disown(); + virtual sp<Overlay> createOverlay( + uint32_t w, uint32_t h, int32_t format); + void disown(); private: LayerBuffer* getOwner() const { Mutex::Autolock _l(mLock); diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index fc23d53..0c347cc 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -48,7 +48,7 @@ void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) { // must only be called once. mDimmerDealer = flinger->getSurfaceHeapManager() - ->createHeap(NATIVE_MEMORY_TYPE_PMEM); + ->createHeap(ISurfaceComposer::eHardware); if (mDimmerDealer != 0) { mDimmerBitmap.init(mDimmerDealer); mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565); @@ -81,7 +81,7 @@ void LayerDim::onDraw(const Region& clip) const mDimmerBitmap.getBitmapSurface(&src); const copybit_rect_t& srect(drect); - copybit_t* copybit = mFlinger->getBlitEngine(); + copybit_device_t* copybit = mFlinger->getBlitEngine(); copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 45496b2..e8de21a 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -38,7 +38,6 @@ #include <utils/String16.h> #include <utils/StopWatch.h> -#include <ui/BlitHardware.h> #include <ui/PixelFormat.h> #include <ui/DisplayInfo.h> #include <ui/EGLDisplaySurface.h> @@ -202,23 +201,6 @@ void SurfaceFlinger::init() { LOGI("SurfaceFlinger is starting"); - // create the shared control-block - mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY); - LOGE_IF(mServerHeap==0, "can't create shared memory dealer"); - - mServerCblkMemory = mServerHeap->allocate(4096); - LOGE_IF(mServerCblkMemory==0, "can't create shared control block"); - - mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer()); - LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); - new(mServerCblk) surface_flinger_cblk_t; - - // create the surface Heap manager, which manages the heaps - // (be it in RAM or VRAM) where surfaces are allocated - // We give 8 MB per client. - mSurfaceHeapManager = new SurfaceHeapManager(8 << 20); - mGPU = new GPUHardware(); - // debugging stuff... char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.showupdates", value, "0"); @@ -244,11 +226,16 @@ SurfaceFlinger::~SurfaceFlinger() glDeleteTextures(1, &mWormholeTexName); } -copybit_t* SurfaceFlinger::getBlitEngine() const +copybit_device_t* SurfaceFlinger::getBlitEngine() const { return graphicPlane(0).displayHardware().getBlitEngine(); } +overlay_device_t* SurfaceFlinger::getOverlayEngine() const +{ + return graphicPlane(0).displayHardware().getOverlayEngine(); +} + sp<IMemory> SurfaceFlinger::getCblk() const { return mServerCblkMemory; @@ -257,7 +244,9 @@ sp<IMemory> SurfaceFlinger::getCblk() const status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback, gpu_info_t* gpu) { - status_t err = mGPU->request(callback, gpu); + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + status_t err = mGPU->request(pid, callback, gpu); return err; } @@ -360,7 +349,26 @@ status_t SurfaceFlinger::readyToRun() LOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); - // + // create the shared control-block + mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY); + LOGE_IF(mServerHeap==0, "can't create shared memory dealer"); + + mServerCblkMemory = mServerHeap->allocate(4096); + LOGE_IF(mServerCblkMemory==0, "can't create shared control block"); + + mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer()); + LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); + new(mServerCblk) surface_flinger_cblk_t; + + // get a reference to the GPU if we have one + mGPU = GPUFactory::getGPU(); + + // create the surface Heap manager, which manages the heaps + // (be it in RAM or VRAM) where surfaces are allocated + // We give 8 MB per client. + mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20); + + GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this); // we only support one display currently @@ -395,7 +403,7 @@ status_t SurfaceFlinger::readyToRun() dcblk->xdpi = hw.getDpiX(); dcblk->ydpi = hw.getDpiY(); dcblk->fps = hw.getRefreshRate(); - dcblk->density = 1.0f; // XXX: do someting more real here... + dcblk->density = hw.getDensity(); asm volatile ("":::"memory"); // Initialize OpenGL|ES @@ -407,6 +415,7 @@ status_t SurfaceFlinger::readyToRun() glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ALIGNMENT, 4); glEnableClientState(GL_VERTEX_ARRAY); glEnable(GL_SCISSOR_TEST); glShadeModel(GL_FLAT); @@ -1679,7 +1688,7 @@ status_t SurfaceFlinger::onTransact( Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) { - mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(NATIVE_MEMORY_TYPE_HEAP); + mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(); const int pgsize = getpagesize(); const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1)); mCblkHeap = new MemoryDealer(cblksize); @@ -1703,10 +1712,6 @@ const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const { return mFlinger->getSurfaceHeapManager(); } -const sp<GPUHardwareInterface>& Client::getGPU() const { - return mFlinger->getGPU(); -} - int32_t Client::generateId(int pid) { const uint32_t i = clz( ~mBitmap ); @@ -1734,25 +1739,11 @@ void Client::free(int32_t id) } } -sp<MemoryDealer> Client::createAllocator(int memory_type) +sp<MemoryDealer> Client::createAllocator(uint32_t flags) { sp<MemoryDealer> allocator; - if (memory_type == NATIVE_MEMORY_TYPE_GPU) { - allocator = getGPU()->request(getClientPid()); - if (allocator == 0) - memory_type = NATIVE_MEMORY_TYPE_PMEM; - } - if (memory_type == NATIVE_MEMORY_TYPE_PMEM) { - allocator = mPMemAllocator; - if (allocator == 0) { - allocator = getSurfaceHeapManager()->createHeap( - NATIVE_MEMORY_TYPE_PMEM); - mPMemAllocator = allocator; - } - } - if (allocator == 0) - allocator = mSharedHeapAllocator; - + allocator = getSurfaceHeapManager()->createHeap( + flags, getClientPid(), mSharedHeapAllocator); return allocator; } diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 1581474..92021d0 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -41,7 +41,8 @@ #include "BootAnimation.h" #include "Barrier.h" -struct copybit_t; +struct copybit_device_t; +struct overlay_device_t; namespace android { @@ -74,7 +75,7 @@ public: int32_t generateId(int pid); void free(int32_t id); status_t bindLayer(LayerBaseClient* layer, int32_t id); - sp<MemoryDealer> createAllocator(int memory_type); + sp<MemoryDealer> createAllocator(uint32_t memory_type); inline bool isValid(int32_t i) const; inline const uint8_t* inUseArray() const; @@ -92,7 +93,6 @@ public: private: int getClientPid() const { return mPid; } - const sp<GPUHardwareInterface>& getGPU() const; int mPid; uint32_t mBitmap; @@ -179,7 +179,8 @@ public: return mGPU; } - copybit_t* getBlitEngine() const; + copybit_device_t* getBlitEngine() const; + overlay_device_t* getOverlayEngine() const; private: friend class BClient; diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp index 3852d51..77bc576 100644 --- a/libs/surfaceflinger/VRamHeap.cpp +++ b/libs/surfaceflinger/VRamHeap.cpp @@ -37,6 +37,8 @@ #include <GLES/eglnatives.h> +#include "GPUHardware/GPUHardware.h" +#include "SurfaceFlinger.h" #include "VRamHeap.h" #if HAVE_ANDROID_OS @@ -59,8 +61,9 @@ int SurfaceHeapManager::global_pmem_heap = 0; // --------------------------------------------------------------------------- -SurfaceHeapManager::SurfaceHeapManager(size_t clientHeapSize) - : mClientHeapSize(clientHeapSize) +SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, + size_t clientHeapSize) + : mFlinger(flinger), mClientHeapSize(clientHeapSize) { SurfaceHeapManager::global_pmem_heap = 1; } @@ -81,25 +84,53 @@ void SurfaceHeapManager::onFirstRef() } } -sp<MemoryDealer> SurfaceHeapManager::createHeap(int type) +sp<MemoryDealer> SurfaceHeapManager::createHeap( + uint32_t flags, + pid_t client_pid, + const sp<MemoryDealer>& defaultAllocator) { - if (!global_pmem_heap && type==NATIVE_MEMORY_TYPE_PMEM) - type = NATIVE_MEMORY_TYPE_HEAP; - - const sp<PMemHeap>& heap(mPMemHeap); sp<MemoryDealer> dealer; - switch (type) { - case NATIVE_MEMORY_TYPE_HEAP: - dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap"); - break; - case NATIVE_MEMORY_TYPE_PMEM: - if (heap != 0) { - dealer = new MemoryDealer( - heap->createClientHeap(), - heap->getAllocator()); + if (flags & ISurfaceComposer::eGPU) { + // don't grant GPU memory if GPU is disabled + char value[PROPERTY_VALUE_MAX]; + property_get("debug.egl.hw", value, "1"); + if (atoi(value) == 0) { + flags &= ~ISurfaceComposer::eGPU; + } + } + + if (flags & ISurfaceComposer::eGPU) { + // FIXME: this is msm7201A specific, where gpu surfaces may not be secure + if (!(flags & ISurfaceComposer::eSecure)) { + // if GPU doesn't work, we try eHardware + flags |= ISurfaceComposer::eHardware; + // asked for GPU memory, try that first + dealer = mFlinger->getGPU()->request(client_pid); + } + } + + if (dealer == NULL) { + if (defaultAllocator != NULL) + // if a default allocator is given, use that + dealer = defaultAllocator; + } + + if (dealer == NULL) { + // always try h/w accelerated memory first + if (global_pmem_heap) { + const sp<PMemHeap>& heap(mPMemHeap); + if (dealer == NULL && heap != NULL) { + dealer = new MemoryDealer( + heap->createClientHeap(), + heap->getAllocator()); + } } - break; + } + + if (dealer == NULL) { + // return the ashmem allocator (software rendering) + dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap"); } return dealer; } @@ -122,22 +153,8 @@ sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const // --------------------------------------------------------------------------- -PMemHeapInterface::PMemHeapInterface(int fd, size_t size) - : MemoryHeapBase(fd, size) { -} -PMemHeapInterface::PMemHeapInterface(const char* device, size_t size) - : MemoryHeapBase(device, size) { -} -PMemHeapInterface::PMemHeapInterface(size_t size, uint32_t flags, char const * name) - : MemoryHeapBase(size, flags, name) { -} -PMemHeapInterface::~PMemHeapInterface() { -} - -// --------------------------------------------------------------------------- - PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved) - : PMemHeapInterface(device, size) + : MemoryHeapBase(device, size) { //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); if (base() != MAP_FAILED) { diff --git a/libs/surfaceflinger/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h index 03e0336..9140167 100644 --- a/libs/surfaceflinger/VRamHeap.h +++ b/libs/surfaceflinger/VRamHeap.h @@ -27,16 +27,19 @@ namespace android { class PMemHeap; class MemoryHeapPmem; +class SurfaceFlinger; // --------------------------------------------------------------------------- class SurfaceHeapManager : public RefBase { public: - SurfaceHeapManager(size_t clientHeapSize); + SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize); virtual ~SurfaceHeapManager(); virtual void onFirstRef(); - sp<MemoryDealer> createHeap(int type); + /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */ + sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0, + const sp<MemoryDealer>& defaultAllocator = 0); // used for debugging only... sp<SimpleBestFitAllocator> getAllocator(int type) const; @@ -44,6 +47,7 @@ public: private: sp<PMemHeap> getHeap(int type) const; + sp<SurfaceFlinger> mFlinger; mutable Mutex mLock; size_t mClientHeapSize; sp<PMemHeap> mPMemHeap; @@ -52,19 +56,7 @@ private: // --------------------------------------------------------------------------- -class PMemHeapInterface : public MemoryHeapBase -{ -public: - PMemHeapInterface(int fd, size_t size); - PMemHeapInterface(const char* device, size_t size = 0); - PMemHeapInterface(size_t size, uint32_t flags = 0, char const * name = NULL); - virtual ~PMemHeapInterface(); - virtual sp<MemoryHeapPmem> createClientHeap() = 0; -}; - -// --------------------------------------------------------------------------- - -class PMemHeap : public PMemHeapInterface +class PMemHeap : public MemoryHeapBase { public: PMemHeap(const char* const vram, |