make multi-display more real
- displays are represented by a binder on the client side
- c++ clients can now create and modify displays
Change-Id: I203ea5b4beae0819d742ec5171c27568f4e8354b
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ac3fb90..f2b49e8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -161,6 +161,39 @@
return bclient;
}
+sp<IBinder> SurfaceFlinger::createDisplay()
+{
+ class DisplayToken : public BBinder {
+ sp<SurfaceFlinger> flinger;
+ virtual ~DisplayToken() {
+ // no more references, this display must be terminated
+ Mutex::Autolock _l(flinger->mStateLock);
+ flinger->mCurrentState.displays.removeItem(this);
+ flinger->setTransactionFlags(eDisplayTransactionNeeded);
+ }
+ public:
+ DisplayToken(const sp<SurfaceFlinger>& flinger)
+ : flinger(flinger) {
+ }
+ };
+
+ sp<BBinder> token = new DisplayToken(this);
+
+ Mutex::Autolock _l(mStateLock);
+ DisplayDeviceState info(intptr_t(token.get())); // FIXME: we shouldn't use the address for the id
+ mCurrentState.displays.add(token, info);
+
+ return token;
+}
+
+sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
+ if (uint32_t(id) >= DisplayDevice::DISPLAY_ID_COUNT) {
+ ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
+ return NULL;
+ }
+ return mDefaultDisplays[id];
+}
+
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
@@ -358,7 +391,8 @@
exit(0);
}
- sp<SurfaceTextureClient> stc(new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(fbs->getBufferQueue())));
+ sp<SurfaceTextureClient> stc(new SurfaceTextureClient(
+ static_cast<sp<ISurfaceTexture> >(fbs->getBufferQueue())));
// initialize the config and context
int format;
@@ -368,9 +402,14 @@
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
// initialize our main display hardware
- mCurrentState.displays.add(DisplayDevice::DISPLAY_ID_MAIN, DisplayDeviceState());
- sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig);
- mDisplays.add(DisplayDevice::DISPLAY_ID_MAIN, hw);
+
+ for (size_t i=0 ; i<DisplayDevice::DISPLAY_ID_COUNT ; i++) {
+ mDefaultDisplays[i] = new BBinder();
+ mCurrentState.displays.add(mDefaultDisplays[i], DisplayDeviceState(i));
+ }
+ sp<DisplayDevice> hw = new DisplayDevice(this,
+ DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig);
+ mDisplays.add(hw->getDisplayId(), hw);
// initialize OpenGL ES
EGLSurface surface = hw->getEGLSurface();
@@ -571,8 +610,7 @@
}
void SurfaceFlinger::handleMessageTransaction() {
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- uint32_t transactionFlags = peekTransactionFlags(mask);
+ uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
if (transactionFlags) {
handleTransaction(transactionFlags);
}
@@ -795,8 +833,7 @@
// with mStateLock held to guarantee that mCurrentState won't change
// until the transaction is committed.
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- transactionFlags = getTransactionFlags(mask);
+ transactionFlags = getTransactionFlags(eTransactionMask);
handleTransactionLocked(transactionFlags);
mLastTransactionTime = systemTime() - now;
@@ -832,12 +869,12 @@
* Perform our own transaction if needed
*/
- if (transactionFlags & eTransactionNeeded) {
+ if (transactionFlags & eDisplayTransactionNeeded) {
// 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);
+ const KeyedVector< wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
+ const KeyedVector< wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
const size_t cc = curr.size();
@@ -848,7 +885,8 @@
// 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) {
+ const ssize_t j = curr.indexOfKey(draw.keyAt(i));
+ if (j < 0) {
// in drawing state but not in current state
if (draw[i].id != DisplayDevice::DISPLAY_ID_MAIN) {
mDisplays.removeItem(draw[i].id);
@@ -857,14 +895,32 @@
}
} else {
// this display is in both lists. see if something changed.
- const DisplayDeviceState& state(curr[i]);
+ const DisplayDeviceState& state(curr[j]);
+ if (state.surface != draw[i].surface) {
+ // changing the surface is like destroying and
+ // recreating the DisplayDevice
+
+ sp<SurfaceTextureClient> stc(
+ new SurfaceTextureClient(state.surface));
+
+ sp<DisplayDevice> disp = new DisplayDevice(this,
+ state.id, stc, 0, mEGLConfig);
+
+ disp->setLayerStack(state.layerStack);
+ disp->setOrientation(state.orientation);
+ // TODO: take viewport and frame into account
+ mDisplays.replaceValueFor(state.id, disp);
+ }
if (state.layerStack != draw[i].layerStack) {
const sp<DisplayDevice>& disp(getDisplayDevice(state.id));
disp->setLayerStack(state.layerStack);
}
- if (curr[i].orientation != draw[i].orientation) {
+ if (state.orientation != draw[i].orientation ||
+ state.viewport != draw[i].viewport ||
+ state.frame != draw[i].frame) {
const sp<DisplayDevice>& disp(getDisplayDevice(state.id));
disp->setOrientation(state.orientation);
+ // TODO: take viewport and frame into account
}
}
}
@@ -872,10 +928,14 @@
// 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) {
+ if (draw.indexOfKey(curr.keyAt(i)) < 0) {
// FIXME: we need to pass the surface here
- sp<DisplayDevice> disp = new DisplayDevice(this, curr[i].id, 0, 0, mEGLConfig);
- mDisplays.add(curr[i].id, disp);
+ const DisplayDeviceState& state(curr[i]);
+ sp<SurfaceTextureClient> stc(
+ new SurfaceTextureClient(state.surface));
+ sp<DisplayDevice> disp = new DisplayDevice(this, state.id,
+ stc, 0, mEGLConfig);
+ mDisplays.add(state.id, disp);
}
}
}
@@ -1358,33 +1418,21 @@
return old;
}
-
void SurfaceFlinger::setTransactionState(
const Vector<ComposerState>& state,
const Vector<DisplayState>& displays,
uint32_t flags)
{
Mutex::Autolock _l(mStateLock);
-
- int orientation = DisplayState::eOrientationUnchanged;
- if (displays.size()) {
- // TODO: handle all displays
- orientation = displays[0].orientation;
- }
-
uint32_t transactionFlags = 0;
- // FIXME: don't hardcode display id here
- if (mCurrentState.displays.valueFor(0).orientation != orientation) {
- if (uint32_t(orientation) <= DisplayState::eOrientation270) {
- mCurrentState.displays.editValueFor(0).orientation = orientation;
- transactionFlags |= eTransactionNeeded;
- } else if (orientation != DisplayState::eOrientationUnchanged) {
- ALOGW("setTransactionState: ignoring unrecognized orientation: %d",
- orientation);
- }
+
+ size_t count = displays.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const DisplayState& s(displays[i]);
+ transactionFlags |= setDisplayStateLocked(s);
}
- const size_t count = state.size();
+ count = state.size();
for (size_t i=0 ; i<count ; i++) {
const ComposerState& s(state[i]);
sp<Client> client( static_cast<Client *>(s.client.get()) );
@@ -1413,6 +1461,105 @@
}
}
+uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
+{
+ uint32_t flags = 0;
+ DisplayDeviceState& disp(mCurrentState.displays.editValueFor(s.token));
+ if (disp.id >= 0) {
+ const uint32_t what = s.what;
+ if (what & DisplayState::eSurfaceChanged) {
+ if (disp.surface->asBinder() != s.surface->asBinder()) {
+ disp.surface = s.surface;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
+ if (what & DisplayState::eLayerStackChanged) {
+ if (disp.layerStack != s.layerStack) {
+ disp.layerStack = s.layerStack;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
+ if (what & DisplayState::eTransformChanged) {
+ if (disp.orientation != s.orientation) {
+ disp.orientation = s.orientation;
+ flags |= eDisplayTransactionNeeded;
+ }
+ if (disp.frame != s.frame) {
+ disp.frame = s.frame;
+ flags |= eDisplayTransactionNeeded;
+ }
+ if (disp.viewport != s.viewport) {
+ disp.viewport = s.viewport;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
+ }
+ return flags;
+}
+
+uint32_t SurfaceFlinger::setClientStateLocked(
+ const sp<Client>& client,
+ const layer_state_t& s)
+{
+ uint32_t flags = 0;
+ sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
+ if (layer != 0) {
+ const uint32_t what = s.what;
+ if (what & layer_state_t::ePositionChanged) {
+ if (layer->setPosition(s.x, s.y))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eLayerChanged) {
+ // NOTE: index needs to be calculated before we update the state
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setLayer(s.z)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eSizeChanged) {
+ if (layer->setSize(s.w, s.h)) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eAlphaChanged) {
+ if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eMatrixChanged) {
+ if (layer->setMatrix(s.matrix))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eTransparentRegionChanged) {
+ if (layer->setTransparentRegionHint(s.transparentRegion))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eVisibilityChanged) {
+ if (layer->setFlags(s.flags, s.mask))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eCropChanged) {
+ if (layer->setCrop(s.crop))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eLayerStackChanged) {
+ // NOTE: index needs to be calculated before we update the state
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setLayerStack(s.layerStack)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ }
+ return flags;
+}
+
sp<ISurface> SurfaceFlinger::createLayer(
ISurfaceComposerClient::surface_data_t* params,
const String8& name,
@@ -1554,69 +1701,6 @@
return err;
}
-uint32_t SurfaceFlinger::setClientStateLocked(
- const sp<Client>& client,
- const layer_state_t& s)
-{
- uint32_t flags = 0;
- sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
- if (layer != 0) {
- const uint32_t what = s.what;
- if (what & layer_state_t::ePositionChanged) {
- if (layer->setPosition(s.x, s.y))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eLayerChanged) {
- // NOTE: index needs to be calculated before we update the state
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayer(s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- if (what & layer_state_t::eSizeChanged) {
- if (layer->setSize(s.w, s.h)) {
- flags |= eTraversalNeeded;
- }
- }
- if (what & layer_state_t::eAlphaChanged) {
- if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eTransparentRegionChanged) {
- if (layer->setTransparentRegionHint(s.transparentRegion))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eVisibilityChanged) {
- if (layer->setFlags(s.flags, s.mask))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eCropChanged) {
- if (layer->setCrop(s.crop))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eLayerStackChanged) {
- // NOTE: index needs to be calculated before we update the state
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayerStack(s.layerStack)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- }
- return flags;
-}
-
// ---------------------------------------------------------------------------
void SurfaceFlinger::onScreenAcquired() {
@@ -1964,7 +2048,10 @@
return NO_ERROR;
}
case 1005:{ // force transaction
- setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
+ setTransactionFlags(
+ eTransactionNeeded|
+ eDisplayTransactionNeeded|
+ eTraversalNeeded);
return NO_ERROR;
}
case 1006:{ // send empty update
@@ -2305,8 +2392,11 @@
// ---------------------------------------------------------------------------
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
- : id(DisplayDevice::DISPLAY_ID_MAIN), layerStack(0), orientation(0) {
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState() : id(-1) {
+}
+
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(int32_t id)
+ : id(id), layerStack(0), orientation(0) {
}
// ---------------------------------------------------------------------------