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
This commit is contained in:
Mathias Agopian 2012-08-21 23:34:09 -07:00
parent 7c9e82633c
commit e60b0687c8
5 changed files with 171 additions and 115 deletions

View File

@ -68,12 +68,12 @@ void checkGLErrors()
DisplayDevice::DisplayDevice( DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger, const sp<SurfaceFlinger>& flinger,
int display, int32_t display, int32_t hwcDisplayId,
const sp<ANativeWindow>& nativeWindow, const sp<ANativeWindow>& nativeWindow,
const sp<FramebufferSurface>& framebufferSurface, const sp<FramebufferSurface>& framebufferSurface,
EGLConfig config) EGLConfig config)
: mFlinger(flinger), : mFlinger(flinger),
mId(display), mId(display), mHwcDisplayId(hwcDisplayId),
mNativeWindow(nativeWindow), mNativeWindow(nativeWindow),
mFramebufferSurface(framebufferSurface), mFramebufferSurface(framebufferSurface),
mDisplay(EGL_NO_DISPLAY), mDisplay(EGL_NO_DISPLAY),

View File

@ -62,7 +62,7 @@ public:
DisplayDevice( DisplayDevice(
const sp<SurfaceFlinger>& flinger, const sp<SurfaceFlinger>& flinger,
int dpy, int32_t dpy, int32_t hwcDisplayId,
const sp<ANativeWindow>& nativeWindow, const sp<ANativeWindow>& nativeWindow,
const sp<FramebufferSurface>& framebufferSurface, const sp<FramebufferSurface>& framebufferSurface,
EGLConfig config); EGLConfig config);
@ -96,6 +96,7 @@ public:
const Transform& getTransform() const { return mGlobalTransform; } const Transform& getTransform() const { return mGlobalTransform; }
uint32_t getLayerStack() const { return mLayerStack; } uint32_t getLayerStack() const { return mLayerStack; }
int32_t getDisplayId() const { return mId; } int32_t getDisplayId() const { return mId; }
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
status_t compositionComplete() const; status_t compositionComplete() const;
@ -132,6 +133,7 @@ private:
*/ */
sp<SurfaceFlinger> mFlinger; sp<SurfaceFlinger> mFlinger;
int32_t mId; int32_t mId;
int32_t mHwcDisplayId;
// ANativeWindow this display is rendering into // ANativeWindow this display is rendering into
sp<ANativeWindow> mNativeWindow; sp<ANativeWindow> mNativeWindow;

View File

@ -194,13 +194,13 @@ HWComposer::HWComposer(
framebuffer_device_t const* fbDev) framebuffer_device_t const* fbDev)
: mFlinger(flinger), : mFlinger(flinger),
mModule(0), mHwc(0), mNumDisplays(1), mCapacity(0), mModule(0), mHwc(0), mNumDisplays(1), mCapacity(0),
mNumOVLayers(0), mNumFBLayers(0),
mCBContext(new cb_context), mCBContext(new cb_context),
mEventHandler(handler), mRefreshPeriod(0), mEventHandler(handler),
mVSyncCount(0), mDebugForceFakeVSync(false) mVSyncCount(0), mDebugForceFakeVSync(false)
{ {
for (size_t i = 0; i < MAX_DISPLAYS; i++) for (size_t i =0 ; i<MAX_DISPLAYS ; i++) {
mLists[i] = NULL; mLists[i] = 0;
}
char value[PROPERTY_VALUE_MAX]; char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.no_hw_vsync", value, "0"); property_get("debug.sf.no_hw_vsync", value, "0");
@ -232,6 +232,10 @@ HWComposer::HWComposer(
mHwc->registerProcs(mHwc, &mCBContext->procs); 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 // always turn vsync off when we start
needVSyncThread = false; needVSyncThread = false;
if (hwcHasVsyncEvent(mHwc)) { if (hwcHasVsyncEvent(mHwc)) {
@ -239,7 +243,7 @@ HWComposer::HWComposer(
int period; int period;
if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) { if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) {
mRefreshPeriod = nsecs_t(period); mDisplayData[0].refresh = nsecs_t(period);
} }
} else { } else {
needVSyncThread = true; needVSyncThread = true;
@ -255,17 +259,17 @@ HWComposer::HWComposer(
if (fbDev) { if (fbDev) {
if (mRefreshPeriod == 0) { if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
mRefreshPeriod = nsecs_t(1e9 / fbDev->fps); mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / fbDev->fps);
ALOGW("getting VSYNC period from fb HAL: %lld", mRefreshPeriod); ALOGW("getting VSYNC period from fb HAL: %lld", mDisplayData[0].refresh);
} }
mDpiX = fbDev->xdpi; mDisplayData[HWC_DISPLAY_PRIMARY].xdpi = fbDev->xdpi;
mDpiY = fbDev->ydpi; mDisplayData[HWC_DISPLAY_PRIMARY].ydpi = fbDev->ydpi;
} }
if (mRefreshPeriod == 0) { if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
mRefreshPeriod = nsecs_t(1e9 / 60.0); mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / 60.0);
ALOGW("getting VSYNC period thin air: %lld", mRefreshPeriod); ALOGW("getting VSYNC period thin air: %lld", mDisplayData[0].refresh);
} }
if (needVSyncThread) { if (needVSyncThread) {
@ -276,8 +280,9 @@ HWComposer::HWComposer(
HWComposer::~HWComposer() { HWComposer::~HWComposer() {
hwcEventControl(mHwc, 0, EVENT_VSYNC, 0); 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]); free(mLists[i]);
}
if (mVSyncThread != NULL) { if (mVSyncThread != NULL) {
mVSyncThread->requestExitAndWait(); mVSyncThread->requestExitAndWait();
} }
@ -315,8 +320,32 @@ void HWComposer::vsync(int dpy, int64_t timestamp) {
mLastHwVSync = 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 { nsecs_t HWComposer::getRefreshPeriod() const {
return mRefreshPeriod; return mDisplayData[0].refresh;
} }
nsecs_t HWComposer::getRefreshTimestamp() const { nsecs_t HWComposer::getRefreshTimestamp() const {
@ -325,15 +354,15 @@ nsecs_t HWComposer::getRefreshTimestamp() const {
// the refresh period and whatever closest timestamp we have. // the refresh period and whatever closest timestamp we have.
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
nsecs_t now = systemTime(CLOCK_MONOTONIC); nsecs_t now = systemTime(CLOCK_MONOTONIC);
return now - ((now - mLastHwVSync) % mRefreshPeriod); return now - ((now - mLastHwVSync) % mDisplayData[0].refresh);
} }
float HWComposer::getDpiX() const { float HWComposer::getDpiX() const {
return mDpiX; return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi;
} }
float HWComposer::getDpiY() const { float HWComposer::getDpiY() const {
return mDpiY; return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi;
} }
void HWComposer::eventControl(int event, int enabled) { 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) { status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
// FIXME: handle multiple displays if (!mTokens.hasBit(id)) {
if (uint32_t(id) >= MAX_DISPLAYS)
return BAD_INDEX; return BAD_INDEX;
}
// FIXME: handle multiple displays
if (mHwc) { if (mHwc) {
// TODO: must handle multiple displays here // TODO: must handle multiple displays here
// mLists[0] is NULL only when this is called from the constructor // 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; return NO_ERROR;
} }
status_t HWComposer::prepare() const { status_t HWComposer::prepare() {
int err = hwcPrepare(mHwc, mNumDisplays, int err = hwcPrepare(mHwc, mNumDisplays,
const_cast<hwc_display_contents_1_t**>(mLists)); const_cast<hwc_display_contents_1_t**>(mLists));
if (err == NO_ERROR) { if (err == NO_ERROR) {
// here we're just making sure that "skip" layers are set // here we're just making sure that "skip" layers are set
@ -388,65 +419,58 @@ status_t HWComposer::prepare() const {
// think is almost possible. // think is almost possible.
// TODO: must handle multiple displays here // TODO: must handle multiple displays here
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
size_t numOVLayers = 0; size_t count = getNumLayers(0);
size_t numFBLayers = 0; struct hwc_display_contents_1* disp = mLists[0];
size_t count = getNumLayers(0); mDisplayData[0].hasFbComp = false;
mDisplayData[0].hasOvComp = false;
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
int compositionType; hwc_layer_1_t* l = &disp->hwLayers[i];
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
hwc_layer_1_t* l = &mLists[0]->hwLayers[i];
if (l->flags & HWC_SKIP_LAYER) { if (l->flags & HWC_SKIP_LAYER) {
l->compositionType = HWC_FRAMEBUFFER; l->compositionType = HWC_FRAMEBUFFER;
} }
compositionType = l->compositionType; if (l->compositionType == HWC_FRAMEBUFFER)
} else { mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
// mList really has hwc_layer_list_t memory layout if (l->compositionType == HWC_OVERLAY)
hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(mLists[0]); mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
hwc_layer_t* l = &list0->hwLayers[i];
if (l->flags & HWC_SKIP_LAYER) {
l->compositionType = HWC_FRAMEBUFFER;
}
compositionType = l->compositionType;
} }
} else {
switch (compositionType) { size_t count = getNumLayers(0);
case HWC_OVERLAY: hwc_layer_list_t* disp = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
numOVLayers++; mDisplayData[0].hasFbComp = false;
break; mDisplayData[0].hasOvComp = false;
case HWC_FRAMEBUFFER: for (size_t i=0 ; i<count ; i++) {
numFBLayers++; hwc_layer_t* l = &disp->hwLayers[i];
break; if (l->flags & HWC_SKIP_LAYER) {
l->compositionType = HWC_FRAMEBUFFER;
}
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; return (status_t)err;
} }
size_t HWComposer::getLayerCount(int32_t id, int type) const { bool HWComposer::hasHwcComposition(int32_t id) const {
// FIXME: handle multiple displays if (!mTokens.hasBit(id))
if (uint32_t(id) >= MAX_DISPLAYS) { return false;
// FIXME: in practice this is only use to know return mDisplayData[id].hasOvComp;
// if we have at least one layer of type.
return (type == HWC_FRAMEBUFFER) ? 1 : 0;
}
switch (type) {
case HWC_OVERLAY:
return mNumOVLayers;
case HWC_FRAMEBUFFER:
return mNumFBLayers;
}
return 0;
} }
status_t HWComposer::commit(void* fbDisplay, void* fbSurface) const { bool HWComposer::hasGlesComposition(int32_t id) const {
if (!mTokens.hasBit(id))
return false;
return mDisplayData[id].hasFbComp;
}
status_t HWComposer::commit() const {
int err = NO_ERROR; int err = NO_ERROR;
if (mHwc) { if (mHwc) {
void* fbDisplay = eglGetCurrentDisplay();
void* fbSurface = eglGetCurrentSurface(EGL_DRAW);
err = hwcSet(mHwc, fbDisplay, fbSurface, mNumDisplays, err = hwcSet(mHwc, fbDisplay, fbSurface, mNumDisplays,
const_cast<hwc_display_contents_1_t**>(mLists)); const_cast<hwc_display_contents_1_t**>(mLists));
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) { 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 * returns an iterator initialized at a given index in the layer list
*/ */
HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) { HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
// FIXME: handle multiple displays if (!mTokens.hasBit(id))
if (uint32_t(id) >= MAX_DISPLAYS)
return LayerListIterator(); return LayerListIterator();
// FIXME: handle multiple displays
if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0])) if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
return LayerListIterator(); return LayerListIterator();
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) { 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) HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
: mHwc(hwc), mEnabled(false), : mHwc(hwc), mEnabled(false),
mNextFakeVSync(0), mNextFakeVSync(0),
mRefreshPeriod(hwc.mRefreshPeriod) mRefreshPeriod(hwc.getRefreshPeriod())
{ {
} }

View File

@ -28,6 +28,7 @@
#include <utils/Thread.h> #include <utils/Thread.h>
#include <utils/Timers.h> #include <utils/Timers.h>
#include <utils/Vector.h> #include <utils/Vector.h>
#include <utils/BitSet.h>
extern "C" int clock_nanosleep(clockid_t clock_id, int flags, extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *request, const struct timespec *request,
@ -70,14 +71,26 @@ public:
status_t initCheck() const; 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 // Asks the HAL what it can do
status_t prepare() const; status_t prepare();
// disable hwc until next createWorkList // disable hwc until next createWorkList
status_t disable(); status_t disable();
// commits the list // commits the list
status_t commit(void* fbDisplay, void* fbSurface) const; status_t commit() const;
// release hardware resources and blank screen // release hardware resources and blank screen
status_t release() const; status_t release() const;
@ -88,9 +101,11 @@ public:
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED. // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
status_t createWorkList(int32_t id, size_t numLayers); status_t createWorkList(int32_t id, size_t numLayers);
// get number of layers of the given type as updated in prepare(). // does this display have layers handled by HWC
// type is HWC_OVERLAY or HWC_FRAMEBUFFER bool hasHwcComposition(int32_t id) const;
size_t getLayerCount(int32_t id, int type) const;
// does this display have layers handled by GLES
bool hasGlesComposition(int32_t id) const;
// needed forward declarations // needed forward declarations
class LayerListIterator; class LayerListIterator;
@ -237,26 +252,32 @@ private:
inline void vsync(int dpy, int64_t timestamp); 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; sp<SurfaceFlinger> mFlinger;
hw_module_t const* mModule; hw_module_t const* mModule;
struct hwc_composer_device_1* mHwc; struct hwc_composer_device_1* mHwc;
// invariant: mLists[0] != NULL iff mHwc != NULL // invariant: mLists[0] != NULL iff mHwc != NULL
// TODO: decide whether mLists[i>0] should be non-NULL when display i is // mLists[i>0] can be NULL. that display is to be ignored
// not attached/enabled.
struct hwc_display_contents_1* mLists[MAX_DISPLAYS]; struct hwc_display_contents_1* mLists[MAX_DISPLAYS];
DisplayData mDisplayData[MAX_DISPLAYS];
size_t mNumDisplays; size_t mNumDisplays;
size_t mCapacity; size_t mCapacity;
mutable size_t mNumOVLayers;
mutable size_t mNumFBLayers;
cb_context* mCBContext; cb_context* mCBContext;
EventHandler& mEventHandler; EventHandler& mEventHandler;
nsecs_t mRefreshPeriod;
float mDpiX;
float mDpiY;
size_t mVSyncCount; size_t mVSyncCount;
sp<VSyncThread> mVSyncThread; sp<VSyncThread> mVSyncThread;
bool mDebugForceFakeVSync; bool mDebugForceFakeVSync;
BitSet32 mTokens;
// protected by mLock // protected by mLock
mutable Mutex mLock; mutable Mutex mLock;

View File

@ -409,7 +409,8 @@ status_t SurfaceFlinger::readyToRun()
mCurrentState.displays.add(mDefaultDisplays[i], DisplayDeviceState(i)); mCurrentState.displays.add(mDefaultDisplays[i], DisplayDeviceState(i));
} }
sp<DisplayDevice> hw = new DisplayDevice(this, sp<DisplayDevice> hw = new DisplayDevice(this,
DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig); DisplayDevice::DISPLAY_ID_MAIN, HWC_DISPLAY_PRIMARY,
anw, fbs, mEGLConfig);
mDisplays.add(hw->getDisplayId(), hw); mDisplays.add(hw->getDisplayId(), hw);
// initialize OpenGL ES // initialize OpenGL ES
@ -779,29 +780,30 @@ void SurfaceFlinger::setUpHWComposer() {
mHwWorkListDirty = false; mHwWorkListDirty = false;
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]); sp<const DisplayDevice> hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers( const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp<LayerBase> >& currentLayers(
hw->getVisibleLayersSortedByZ()); hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size(); const size_t count = currentLayers.size();
if (hwc.createWorkList(id, count) >= 0) {
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
const sp<LayerBase>& layer(currentLayers[i]);
const int32_t id = hw->getDisplayId(); if (CC_UNLIKELY(workListsDirty)) {
if (hwc.createWorkList(id, count) >= 0) { layer->setGeometry(hw, *cur);
HWComposer::LayerListIterator cur = hwc.begin(id); if (mDebugDisableHWC || mDebugRegion) {
const HWComposer::LayerListIterator end = hwc.end(id); cur->setSkip(true);
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) { }
const sp<LayerBase>& layer(currentLayers[i]);
if (CC_UNLIKELY(workListsDirty)) {
layer->setGeometry(hw, *cur);
if (mDebugDisableHWC || mDebugRegion) {
cur->setSkip(true);
} }
}
/* /*
* update the per-frame h/w composer data for each layer * update the per-frame h/w composer data for each layer
* and build the transparent region of the FB * and build the transparent region of the FB
*/ */
layer->setPerFrameData(hw, *cur); layer->setPerFrameData(hw, *cur);
}
} }
} }
} }
@ -841,21 +843,20 @@ void SurfaceFlinger::postFramebuffer()
HWComposer& hwc(getHwComposer()); HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) { if (hwc.initCheck() == NO_ERROR) {
// FIXME: eventually commit() won't take arguments
// FIXME: EGL spec says: // FIXME: EGL spec says:
// "surface must be bound to the calling thread's current context, // "surface must be bound to the calling thread's current context,
// for the current rendering API." // for the current rendering API."
DisplayDevice::makeCurrent( DisplayDevice::makeCurrent(
getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext); getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext);
hwc.commit(mEGLDisplay, getDefaultDisplayDevice()->getEGLSurface()); hwc.commit();
} }
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]); sp<const DisplayDevice> hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ()); const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size(); const size_t count = currentLayers.size();
if (hwc.initCheck() == NO_ERROR) { int32_t id = hw->getHwcDisplayId();
int32_t id = hw->getDisplayId(); if (id >=0 && hwc.initCheck() == NO_ERROR) {
HWComposer::LayerListIterator cur = hwc.begin(id); HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id); const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i = 0; cur != end && i < count; ++i, ++cur) { for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
@ -951,12 +952,15 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (state.surface->asBinder() != draw[i].surface->asBinder()) { if (state.surface->asBinder() != draw[i].surface->asBinder()) {
// changing the surface is like destroying and // changing the surface is like destroying and
// recreating the DisplayDevice // recreating the DisplayDevice
const int32_t hwcDisplayId =
(uint32_t(state.id) < DisplayDevice::DISPLAY_ID_COUNT) ?
state.id : getHwComposer().allocateDisplayId();
sp<SurfaceTextureClient> stc( sp<SurfaceTextureClient> stc(
new SurfaceTextureClient(state.surface)); new SurfaceTextureClient(state.surface));
sp<DisplayDevice> disp = new DisplayDevice(this, sp<DisplayDevice> disp = new DisplayDevice(this,
state.id, stc, 0, mEGLConfig); state.id, hwcDisplayId, stc, 0, mEGLConfig);
disp->setLayerStack(state.layerStack); disp->setLayerStack(state.layerStack);
disp->setOrientation(state.orientation); disp->setOrientation(state.orientation);
@ -982,10 +986,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
for (size_t i=0 ; i<cc ; i++) { for (size_t i=0 ; i<cc ; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) { if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]); const DisplayDeviceState& state(curr[i]);
const int32_t hwcDisplayId =
(uint32_t(state.id) < DisplayDevice::DISPLAY_ID_COUNT) ?
state.id : getHwComposer().allocateDisplayId();
sp<SurfaceTextureClient> stc( sp<SurfaceTextureClient> stc(
new SurfaceTextureClient(state.surface)); new SurfaceTextureClient(state.surface));
sp<DisplayDevice> disp = new DisplayDevice(this, state.id, sp<DisplayDevice> disp = new DisplayDevice(this,
stc, 0, mEGLConfig); state.id, hwcDisplayId, stc, 0, mEGLConfig);
mDisplays.add(state.id, disp); mDisplays.add(state.id, disp);
} }
} }
@ -1251,12 +1259,13 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty) void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{ {
HWComposer& hwc(getHwComposer()); HWComposer& hwc(getHwComposer());
int32_t id = hw->getDisplayId(); int32_t id = hw->getHwcDisplayId();
HWComposer::LayerListIterator cur = hwc.begin(id); HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id); const HWComposer::LayerListIterator end = hwc.end(id);
const size_t fbLayerCount = hwc.getLayerCount(id, HWC_FRAMEBUFFER); const bool hasGlesComposition = hwc.hasGlesComposition(id);
if (cur==end || fbLayerCount) { const bool hasHwcComposition = hwc.hasHwcComposition(id);
if (cur==end || hasGlesComposition) {
DisplayDevice::makeCurrent(hw, mEGLContext); DisplayDevice::makeCurrent(hw, mEGLContext);
@ -1265,7 +1274,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
glLoadIdentity(); glLoadIdentity();
// Never touch the framebuffer if we don't have any framebuffer layers // Never touch the framebuffer if we don't have any framebuffer layers
if (hwc.getLayerCount(id, HWC_OVERLAY)) { if (hasHwcComposition) {
// when using overlays, we assume a fully transparent framebuffer // when using overlays, we assume a fully transparent framebuffer
// NOTE: we could reduce how much we need to clear, for instance // NOTE: we could reduce how much we need to clear, for instance
// remove where there are opaque FB layers. however, on some // remove where there are opaque FB layers. however, on some