We now have a real list of displays.
displays can be dynamically added or removed, and the
list is part of the SF's transaction.
Change-Id: I4186ea39f1317c0e7c044f869004017738968fab
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7fb825a..f25eb5f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -370,11 +370,12 @@
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
// initialize our main display hardware
- DisplayDevice* const hw = new DisplayDevice(this, 0, anw, mEGLConfig);
- mDisplayDevices[0] = hw;
+ mCurrentState.displays.add(DisplayDevice::DISPLAY_ID_MAIN, DisplayDeviceState());
+ DisplayDevice hw(this, DisplayDevice::DISPLAY_ID_MAIN, anw, mEGLConfig);
+ mDisplays.add(DisplayDevice::DISPLAY_ID_MAIN, hw);
// initialize OpenGL ES
- EGLSurface surface = hw->getEGLSurface();
+ EGLSurface surface = hw.getEGLSurface();
initializeGL(mEGLDisplay, surface);
// start the EventThread
@@ -384,7 +385,10 @@
// initialize the H/W composer
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(this),
- hw->getRefreshPeriod());
+ hw.getRefreshPeriod());
+
+ // initialize our drawing state
+ mDrawingState = mCurrentState;
// We're now ready to accept clients...
mReadyToRunBarrier.open();
@@ -585,9 +589,8 @@
*/
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
-
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
Region opaqueRegion;
Region dirtyRegion;
computeVisibleRegions(currentLayers,
@@ -615,8 +618,8 @@
// build the h/w work list
const bool workListsDirty = mHwWorkListDirty;
mHwWorkListDirty = false;
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ const DisplayDevice& hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
@@ -646,8 +649,8 @@
}
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
// transform the dirty region into this screen's coordinate space
const Transform& planeTransform(hw.getTransform());
@@ -693,7 +696,7 @@
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(0)));
+ DisplayDevice& hw(const_cast<DisplayDevice&>(getDefaultDisplayDevice()));
const Vector< sp<LayerBase> >& layers( hw.getVisibleLayersSortedByZ() );
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
@@ -725,8 +728,8 @@
HWComposer& hwc(getHwComposer());
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
if (hwc.initCheck() == NO_ERROR) {
const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
@@ -746,8 +749,8 @@
hwc.commit(mEGLDisplay, getDefaultDisplayDevice().getEGLSurface());
}
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ const DisplayDevice& hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
if (hwc.initCheck() == NO_ERROR) {
@@ -822,16 +825,52 @@
*/
if (transactionFlags & eTransactionNeeded) {
- if (mCurrentState.orientation != mDrawingState.orientation) {
- // the orientation has changed, recompute all visible regions
- // and invalidate everything.
-
- const int dpy = 0; // FIXME: should be a parameter
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
- hw.setOrientation(mCurrentState.orientation);
- hw.dirtyRegion.set(hw.bounds());
-
+ // here we take advantage of Vector's copy-on-write semantics to
+ // improve performance by skipping the transaction entirely when
+ // know that the lists are identical
+ const KeyedVector<int32_t, DisplayDeviceState>& curr(mCurrentState.displays);
+ const KeyedVector<int32_t, DisplayDeviceState>& draw(mDrawingState.displays);
+ if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
+ const size_t cc = curr.size();
+ const size_t dc = draw.size();
+
+ // find the displays that were removed
+ // (ie: in drawing state but not in current state)
+ // also handle displays that changed
+ // (ie: displays that are in both lists)
+ for (size_t i=0 ; i<dc ; i++) {
+ if (curr.indexOfKey(draw[i].id) < 0) {
+ // in drawing state but not in current state
+ if (draw[i].id != DisplayDevice::DISPLAY_ID_MAIN) {
+ mDisplays.editValueFor(draw[i].id).terminate();
+ mDisplays.removeItem(draw[i].id);
+ } else {
+ ALOGW("trying to remove the main display");
+ }
+ } else {
+ // this display is in both lists. see if something changed.
+ const DisplayDeviceState& state(curr[i]);
+ if (state.layerStack != draw[i].layerStack) {
+ DisplayDevice& disp(mDisplays.editValueFor(state.id));
+ //disp.setLayerStack(state.layerStack);
+ }
+ if (curr[i].orientation != draw[i].orientation) {
+ DisplayDevice& disp(mDisplays.editValueFor(state.id));
+ disp.setOrientation(state.orientation);
+ }
+ }
+ }
+
+ // find displays that were added
+ // (ie: in current state but not in drawing state)
+ for (size_t i=0 ; i<cc ; i++) {
+ if (mDrawingState.displays.indexOfKey(curr[i].id) < 0) {
+ // FIXME: we need to pass the surface here
+ DisplayDevice disp(this, curr[i].id, 0, mEGLConfig);
+ mDisplays.add(curr[i].id, disp);
+ }
+ }
}
if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
@@ -1011,10 +1050,12 @@
void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
const Region& dirty) {
- // FIXME: update the dirty region of all displays
- // presenting this layer's layer stack.
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(0)));
- hw.dirtyRegion.orSelf(dirty);
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
+ if (hw.getLayerStack() == layerStack) {
+ hw.dirtyRegion.orSelf(dirty);
+ }
+ }
}
void SurfaceFlinger::handlePageFlip()
@@ -1324,9 +1365,10 @@
}
uint32_t transactionFlags = 0;
- if (mCurrentState.orientation != orientation) {
+ // FIXME: don't hardcode display id here
+ if (mCurrentState.displays.valueFor(0).orientation != orientation) {
if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
- mCurrentState.orientation = orientation;
+ mCurrentState.displays.editValueFor(0).orientation = orientation;
transactionFlags |= eTransactionNeeded;
} else if (orientation != eOrientationUnchanged) {
ALOGW("setTransactionState: ignoring unrecognized orientation: %d",
@@ -1416,7 +1458,7 @@
PixelFormat& format)
{
// initialize the surfaces
- switch (format) { // TODO: take h/w into account
+ switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
@@ -1804,7 +1846,7 @@
hw.undefinedRegion.dump(result, "undefinedRegion");
snprintf(buffer, SIZE,
" orientation=%d, canDraw=%d\n",
- mCurrentState.orientation, hw.canDraw());
+ hw.getOrientation(), hw.canDraw());
result.append(buffer);
snprintf(buffer, SIZE,
" last eglSwapBuffers() time: %f us\n"
@@ -2727,9 +2769,8 @@
// ---------------------------------------------------------------------------
-SurfaceFlinger::State::State()
- : orientation(ISurfaceComposer::eOrientationDefault),
- orientationFlags(0) {
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
+ : id(DisplayDevice::DISPLAY_ID_MAIN), layerStack(0), orientation(0) {
}
// ---------------------------------------------------------------------------