summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/DisplayHardware
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2012-08-21 23:34:09 -0700
committerMathias Agopian <mathias@google.com>2012-08-23 16:03:37 -0700
commite60b0687c8d49871d0c8786cabe6851f7a7783b5 (patch)
treeafef903dcaa648d2862278e289c254a99390f400 /services/surfaceflinger/DisplayHardware
parent7c9e82633c5c4f85b896a5879bdb25cdf659646e (diff)
downloadframeworks_native-e60b0687c8d49871d0c8786cabe6851f7a7783b5.zip
frameworks_native-e60b0687c8d49871d0c8786cabe6851f7a7783b5.tar.gz
frameworks_native-e60b0687c8d49871d0c8786cabe6851f7a7783b5.tar.bz2
HWComposer now has its own concept of display IDs
HWComposer can now create IDs representing a display it can deal with. IDs MAIN and HDMI are reserved. SurfaceFlinger associate HWComposer IDs with a DisplayDevice and uses that when it talks to HWComposer. A DisplayDevice doesn't have to have a HWComposer ID, in that case it just can't use h/w composer composition. Change-Id: Iec3d7ac92e0c22bf975052ae2847402f58bade71
Diffstat (limited to 'services/surfaceflinger/DisplayHardware')
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp156
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h45
2 files changed, 123 insertions, 78 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 403b979..dd70232 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -194,13 +194,13 @@ HWComposer::HWComposer(
framebuffer_device_t const* fbDev)
: mFlinger(flinger),
mModule(0), mHwc(0), mNumDisplays(1), mCapacity(0),
- mNumOVLayers(0), mNumFBLayers(0),
mCBContext(new cb_context),
- mEventHandler(handler), mRefreshPeriod(0),
+ mEventHandler(handler),
mVSyncCount(0), mDebugForceFakeVSync(false)
{
- for (size_t i = 0; i < MAX_DISPLAYS; i++)
- mLists[i] = NULL;
+ for (size_t i =0 ; i<MAX_DISPLAYS ; i++) {
+ mLists[i] = 0;
+ }
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.no_hw_vsync", value, "0");
@@ -232,6 +232,10 @@ HWComposer::HWComposer(
mHwc->registerProcs(mHwc, &mCBContext->procs);
}
+ // these IDs are always reserved
+ mTokens.markBit(HWC_DISPLAY_PRIMARY);
+ mTokens.markBit(HWC_DISPLAY_EXTERNAL);
+
// always turn vsync off when we start
needVSyncThread = false;
if (hwcHasVsyncEvent(mHwc)) {
@@ -239,7 +243,7 @@ HWComposer::HWComposer(
int period;
if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) {
- mRefreshPeriod = nsecs_t(period);
+ mDisplayData[0].refresh = nsecs_t(period);
}
} else {
needVSyncThread = true;
@@ -255,17 +259,17 @@ HWComposer::HWComposer(
if (fbDev) {
- if (mRefreshPeriod == 0) {
- mRefreshPeriod = nsecs_t(1e9 / fbDev->fps);
- ALOGW("getting VSYNC period from fb HAL: %lld", mRefreshPeriod);
+ if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
+ mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / fbDev->fps);
+ ALOGW("getting VSYNC period from fb HAL: %lld", mDisplayData[0].refresh);
}
- mDpiX = fbDev->xdpi;
- mDpiY = fbDev->ydpi;
+ mDisplayData[HWC_DISPLAY_PRIMARY].xdpi = fbDev->xdpi;
+ mDisplayData[HWC_DISPLAY_PRIMARY].ydpi = fbDev->ydpi;
}
- if (mRefreshPeriod == 0) {
- mRefreshPeriod = nsecs_t(1e9 / 60.0);
- ALOGW("getting VSYNC period thin air: %lld", mRefreshPeriod);
+ if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
+ mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / 60.0);
+ ALOGW("getting VSYNC period thin air: %lld", mDisplayData[0].refresh);
}
if (needVSyncThread) {
@@ -276,8 +280,9 @@ HWComposer::HWComposer(
HWComposer::~HWComposer() {
hwcEventControl(mHwc, 0, EVENT_VSYNC, 0);
- for (size_t i = 0; i < MAX_DISPLAYS; i++)
+ for (size_t i = 0; i < MAX_DISPLAYS; i++) {
free(mLists[i]);
+ }
if (mVSyncThread != NULL) {
mVSyncThread->requestExitAndWait();
}
@@ -315,8 +320,32 @@ void HWComposer::vsync(int dpy, int64_t timestamp) {
mLastHwVSync = timestamp;
}
+int32_t HWComposer::allocateDisplayId() {
+ if (mTokens.isFull()) {
+ return NO_MEMORY;
+ }
+
+ // FIXME: for now we don't support h/w composition wifi displays
+ return -1;
+
+ int32_t id = mTokens.firstUnmarkedBit();
+ mTokens.markBit(id);
+ return id;
+}
+
+status_t HWComposer::freeDisplayId(int32_t id) {
+ if (id < MAX_DISPLAYS) {
+ return BAD_VALUE;
+ }
+ if (!mTokens.hasBit(id)) {
+ return BAD_INDEX;
+ }
+ mTokens.clearBit(id);
+ return NO_ERROR;
+}
+
nsecs_t HWComposer::getRefreshPeriod() const {
- return mRefreshPeriod;
+ return mDisplayData[0].refresh;
}
nsecs_t HWComposer::getRefreshTimestamp() const {
@@ -325,15 +354,15 @@ nsecs_t HWComposer::getRefreshTimestamp() const {
// the refresh period and whatever closest timestamp we have.
Mutex::Autolock _l(mLock);
nsecs_t now = systemTime(CLOCK_MONOTONIC);
- return now - ((now - mLastHwVSync) % mRefreshPeriod);
+ return now - ((now - mLastHwVSync) % mDisplayData[0].refresh);
}
float HWComposer::getDpiX() const {
- return mDpiX;
+ return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi;
}
float HWComposer::getDpiY() const {
- return mDpiY;
+ return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi;
}
void HWComposer::eventControl(int event, int enabled) {
@@ -354,10 +383,11 @@ void HWComposer::eventControl(int event, int enabled) {
}
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
- // FIXME: handle multiple displays
- if (uint32_t(id) >= MAX_DISPLAYS)
+ if (!mTokens.hasBit(id)) {
return BAD_INDEX;
+ }
+ // FIXME: handle multiple displays
if (mHwc) {
// TODO: must handle multiple displays here
// mLists[0] is NULL only when this is called from the constructor
@@ -376,9 +406,10 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
return NO_ERROR;
}
-status_t HWComposer::prepare() const {
+status_t HWComposer::prepare() {
int err = hwcPrepare(mHwc, mNumDisplays,
const_cast<hwc_display_contents_1_t**>(mLists));
+
if (err == NO_ERROR) {
// here we're just making sure that "skip" layers are set
@@ -388,65 +419,58 @@ status_t HWComposer::prepare() const {
// think is almost possible.
// TODO: must handle multiple displays here
-
- size_t numOVLayers = 0;
- size_t numFBLayers = 0;
- size_t count = getNumLayers(0);
-
- for (size_t i=0 ; i<count ; i++) {
- int compositionType;
- if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
- hwc_layer_1_t* l = &mLists[0]->hwLayers[i];
+ if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
+ size_t count = getNumLayers(0);
+ struct hwc_display_contents_1* disp = mLists[0];
+ mDisplayData[0].hasFbComp = false;
+ mDisplayData[0].hasOvComp = false;
+ for (size_t i=0 ; i<count ; i++) {
+ hwc_layer_1_t* l = &disp->hwLayers[i];
if (l->flags & HWC_SKIP_LAYER) {
l->compositionType = HWC_FRAMEBUFFER;
}
- compositionType = l->compositionType;
- } else {
- // mList really has hwc_layer_list_t memory layout
- hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
- hwc_layer_t* l = &list0->hwLayers[i];
+ if (l->compositionType == HWC_FRAMEBUFFER)
+ mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
+ if (l->compositionType == HWC_OVERLAY)
+ mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
+ }
+ } else {
+ size_t count = getNumLayers(0);
+ hwc_layer_list_t* disp = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
+ mDisplayData[0].hasFbComp = false;
+ mDisplayData[0].hasOvComp = false;
+ for (size_t i=0 ; i<count ; i++) {
+ hwc_layer_t* l = &disp->hwLayers[i];
if (l->flags & HWC_SKIP_LAYER) {
l->compositionType = HWC_FRAMEBUFFER;
}
- compositionType = l->compositionType;
- }
-
- switch (compositionType) {
- case HWC_OVERLAY:
- numOVLayers++;
- break;
- case HWC_FRAMEBUFFER:
- numFBLayers++;
- break;
+ if (l->compositionType == HWC_FRAMEBUFFER)
+ mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
+ if (l->compositionType == HWC_OVERLAY)
+ mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
}
}
- mNumOVLayers = numOVLayers;
- mNumFBLayers = numFBLayers;
}
return (status_t)err;
}
-size_t HWComposer::getLayerCount(int32_t id, int type) const {
- // FIXME: handle multiple displays
- if (uint32_t(id) >= MAX_DISPLAYS) {
- // FIXME: in practice this is only use to know
- // if we have at least one layer of type.
- return (type == HWC_FRAMEBUFFER) ? 1 : 0;
- }
-
+bool HWComposer::hasHwcComposition(int32_t id) const {
+ if (!mTokens.hasBit(id))
+ return false;
+ return mDisplayData[id].hasOvComp;
+}
- switch (type) {
- case HWC_OVERLAY:
- return mNumOVLayers;
- case HWC_FRAMEBUFFER:
- return mNumFBLayers;
- }
- return 0;
+bool HWComposer::hasGlesComposition(int32_t id) const {
+ if (!mTokens.hasBit(id))
+ return false;
+ return mDisplayData[id].hasFbComp;
}
-status_t HWComposer::commit(void* fbDisplay, void* fbSurface) const {
+status_t HWComposer::commit() const {
int err = NO_ERROR;
if (mHwc) {
+ void* fbDisplay = eglGetCurrentDisplay();
+ void* fbSurface = eglGetCurrentSurface(EGL_DRAW);
err = hwcSet(mHwc, fbDisplay, fbSurface, mNumDisplays,
const_cast<hwc_display_contents_1_t**>(mLists));
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
@@ -661,10 +685,10 @@ public:
* returns an iterator initialized at a given index in the layer list
*/
HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
- // FIXME: handle multiple displays
- if (uint32_t(id) >= MAX_DISPLAYS)
+ if (!mTokens.hasBit(id))
return LayerListIterator();
+ // FIXME: handle multiple displays
if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
return LayerListIterator();
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
@@ -741,7 +765,7 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
: mHwc(hwc), mEnabled(false),
mNextFakeVSync(0),
- mRefreshPeriod(hwc.mRefreshPeriod)
+ mRefreshPeriod(hwc.getRefreshPeriod())
{
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index d15c6f4..7bb3f81 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -28,6 +28,7 @@
#include <utils/Thread.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
+#include <utils/BitSet.h>
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *request,
@@ -70,14 +71,26 @@ public:
status_t initCheck() const;
+ // returns a display ID starting at MAX_DISPLAYS, this ID
+ // is to be used with createWorkList (and all other
+ // methods requiring an ID below).
+ // IDs below MAX_DISPLAY are pre-defined and therefore are always valid.
+ // returns a negative error code if an ID cannot be allocated
+ int32_t allocateDisplayId();
+
+ // recycles the given ID and frees the associated worklist.
+ // IDs below MAX_DISPLAYS are not recycled
+ status_t freeDisplayId(int32_t id);
+
+
// Asks the HAL what it can do
- status_t prepare() const;
+ status_t prepare();
// disable hwc until next createWorkList
status_t disable();
// commits the list
- status_t commit(void* fbDisplay, void* fbSurface) const;
+ status_t commit() const;
// release hardware resources and blank screen
status_t release() const;
@@ -88,9 +101,11 @@ public:
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
status_t createWorkList(int32_t id, size_t numLayers);
- // get number of layers of the given type as updated in prepare().
- // type is HWC_OVERLAY or HWC_FRAMEBUFFER
- size_t getLayerCount(int32_t id, int type) const;
+ // does this display have layers handled by HWC
+ bool hasHwcComposition(int32_t id) const;
+
+ // does this display have layers handled by GLES
+ bool hasGlesComposition(int32_t id) const;
// needed forward declarations
class LayerListIterator;
@@ -237,26 +252,32 @@ private:
inline void vsync(int dpy, int64_t timestamp);
+ struct DisplayData {
+ DisplayData() : xdpi(0), ydpi(0), refresh(0),
+ hasFbComp(false), hasOvComp(false) { }
+ float xdpi;
+ float ydpi;
+ nsecs_t refresh;
+ bool hasFbComp;
+ bool hasOvComp;
+ };
+
sp<SurfaceFlinger> mFlinger;
hw_module_t const* mModule;
struct hwc_composer_device_1* mHwc;
// invariant: mLists[0] != NULL iff mHwc != NULL
- // TODO: decide whether mLists[i>0] should be non-NULL when display i is
- // not attached/enabled.
+ // mLists[i>0] can be NULL. that display is to be ignored
struct hwc_display_contents_1* mLists[MAX_DISPLAYS];
+ DisplayData mDisplayData[MAX_DISPLAYS];
size_t mNumDisplays;
size_t mCapacity;
- mutable size_t mNumOVLayers;
- mutable size_t mNumFBLayers;
cb_context* mCBContext;
EventHandler& mEventHandler;
- nsecs_t mRefreshPeriod;
- float mDpiX;
- float mDpiY;
size_t mVSyncCount;
sp<VSyncThread> mVSyncThread;
bool mDebugForceFakeVSync;
+ BitSet32 mTokens;
// protected by mLock
mutable Mutex mLock;