Code drop from //branches/cupcake/...@124589
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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::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.
*
- * 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.
+ * All this code will soon go-away and be replaced by a new architecture
+ * for managing graphics accelerators.
+ *
+ * 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 @@
*
*/
-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; }
-private:
- void revokeNotification();
+ GPUClientHeap(const wp<GPUHardware>& gpu,
+ const sp<MemoryHeapBase>& heap)
+ : MemoryHeapPmem(heap), mGPU(gpu) { }
+protected:
wp<GPUHardware> mGPU;
- sp<IMemoryHeap> mClientHeap;
- int mOwner;
};
-GPUHandle::~GPUHandle() {
+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:
+ sp<SimpleBestFitAllocator> mAllocator;
+protected:
+ wp<GPUHardware> mGPU;
+};
+
+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 @@
// ---------------------------------------------------------------------------
-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 @@
// 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 @@
#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 @@
{
}
-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;
- }
-
- 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();
- }
-
- dealer = mAllocator;
- mOwner = pid;
- if (dealer == 0) {
- mOwner = SURFACE_FAILED;
- }
-
- LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner);
- return dealer;
-}
-
-status_t GPUHardware::request(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();
-
- 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 (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;
+}
- if (mHeapR.isValid()) {
+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);
+ }
+ return dealer;
+}
+
+status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback,
+ ISurfaceComposer::gpu_info_t* gpu)
+{
+ if (callback == 0)
+ return BAD_VALUE;
+
+ sp<IMemory> gpuHandle;
+ LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner);
+ Mutex::Autolock _l(mLock);
+ 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 @@
// 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::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));
+ //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();
}
- 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());
- }
+ 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 @@
sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const {
Mutex::Autolock _l(mLock);
- sp<SimpleBestFitAllocator> allocator = mAllocatorDebug.promote();
- return allocator;
+ return mAllocator;
}
void GPUHardware::unconditionalRevoke()
@@ -456,102 +501,81 @@
// ---------------------------------------------------------------------------
-
-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));
-}
-
-void GPUHardware::GPUPart::clear()
-{
- mHeap.clear();
- mHeapWeak.clear();
- mClientHeap.clear();
- surface = false;
-}
-
-void GPUHardware::GPUPart::set(const sp<PMemHeapInterface>& heap)
-{
- mHeapWeak.clear();
- if (heap!=0 && heap->base() == MAP_FAILED) {
- mHeap.clear();
- mClientHeap.clear();
- } else {
- mHeap = heap;
- mClientHeap = mHeap->createClientHeap();
- }
-}
-
-bool GPUHardware::GPUPart::promote()
-{
- //LOGD("mHeapWeak=%p, mHeap=%p", mHeapWeak.unsafe_get(), mHeap.get());
- if (mHeap == 0) {
- mHeap = mHeapWeak.promote();
- }
- if (mHeap != 0) {
- if (mClientHeap != 0) {
- mClientHeap->revoke();
- }
- mClientHeap = mHeap->createClientHeap();
- } else {
- surface = false;
- }
- return mHeap != 0;
-}
-
-sp<IMemory> GPUHardware::GPUPart::map(bool clear)
-{
+sp<IMemory> GPUHardware::GPUArea::map() {
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());
- }
+ if (clientHeap != 0 && heap != 0) {
+ memory = clientHeap->mapMemory(0, heap->virtualSize());
}
return memory;
}
-void GPUHardware::GPUPart::release(bool dispose)
+void GPUHardware::Client::createClientHeaps()
{
- if (mClientHeap != 0) {
- mClientHeap->revoke();
- mClientHeap.clear();
+ 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::Client::revokeAllHeaps()
+{
+ if (smi.clientHeap != 0)
+ smi.clientHeap->revoke();
+ if (ebi.clientHeap != 0)
+ ebi.clientHeap->revoke();
+ if (reg.clientHeap != 0)
+ reg.clientHeap->revoke();
+}
+
+void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback,
+ Client& client)
+{
+ sp<IBinder> binder = callback->asBinder();
+ if (mRegisteredClients.add(binder, client.pid) >= 0) {
+ binder->linkToDeath(this);
}
- 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();
+}
+
+void GPUHardware::binderDied(const wp<IBinder>& who)
+{
+ 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;
+ }
}
}
}
// ---------------------------------------------------------------------------
+
+sp<GPUHardwareInterface> GPUFactory::getGPU()
+{
+ return new GPUHardware();
+}
+
+// ---------------------------------------------------------------------------
}; // namespace android
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 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 @@
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 @@
mSurface = new Surface(clientIndex(),
allocators[0]->getMemoryHeap(),
allocators[1]->getMemoryHeap(),
- memory_type, mIdentity);
+ mIdentity);
return NO_ERROR;
}
@@ -180,7 +183,7 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
{ 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 @@
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 @@
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..3861e681 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -104,7 +104,7 @@
* 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 @@
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 @@
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 @@
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 @@
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..3e616f27 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -33,6 +33,7 @@
class MemoryDealer;
class Region;
+class Overlay;
class LayerBuffer : public LayerBaseClient
{
@@ -56,6 +57,7 @@
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 @@
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 @@
{
// 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 @@
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..e8de21a3 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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
-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 @@
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 @@
private:
int getClientPid() const { return mPid; }
- const sp<GPUHardwareInterface>& getGPU() const;
int mPid;
uint32_t mBitmap;
@@ -179,7 +179,8 @@
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 @@
// ---------------------------------------------------------------------------
-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 @@
}
}
-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;
}
- break;
+ }
+
+ 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());
+ }
+ }
+ }
+
+ if (dealer == NULL) {
+ // return the ashmem allocator (software rendering)
+ dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap");
}
return dealer;
}
@@ -122,22 +153,8 @@
// ---------------------------------------------------------------------------
-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 @@
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 @@
private:
sp<PMemHeap> getHeap(int type) const;
+ sp<SurfaceFlinger> mFlinger;
mutable Mutex mLock;
size_t mClientHeapSize;
sp<PMemHeap> mPMemHeap;
@@ -52,19 +56,7 @@
// ---------------------------------------------------------------------------
-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,