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/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index b2f8889..9ab35b1 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -48,6 +48,11 @@
eSynchronous = 0x01,
};
+ enum {
+ eDisplayIdMain = 0,
+ eDisplayIdHdmi = 1
+ };
+
/* create connection with surface flinger, requires
* ACCESS_SURFACE_FLINGER permission
*/
@@ -57,6 +62,19 @@
*/
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
+ /* return an IDisplayEventConnection */
+ virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
+
+ /* create a display with given id.
+ * requires ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual sp<IBinder> createDisplay() = 0;
+
+ /* get the token for the existing default displays. possible values
+ * for id are eDisplayIdMain and eDisplayIdHdmi.
+ */
+ virtual sp<IBinder> getBuiltInDisplay(int32_t id) = 0;
+
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual void setTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags) = 0;
@@ -66,6 +84,11 @@
*/
virtual void bootFinished() = 0;
+ /* verify that an ISurfaceTexture was created by SurfaceFlinger.
+ */
+ virtual bool authenticateSurfaceTexture(
+ const sp<ISurfaceTexture>& surface) const = 0;
+
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
*/
@@ -74,13 +97,6 @@
uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
uint32_t maxLayerZ) = 0;
- /* verify that an ISurfaceTexture was created by SurfaceFlinger.
- */
- virtual bool authenticateSurfaceTexture(
- const sp<ISurfaceTexture>& surface) const = 0;
-
- /* return an IDisplayEventConnection */
- virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
/* triggers screen off and waits for it to complete */
virtual void blank() = 0;
@@ -106,13 +122,15 @@
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
- GET_DISPLAY_INFO,
- SET_TRANSACTION_STATE,
- CAPTURE_SCREEN,
- AUTHENTICATE_SURFACE,
CREATE_DISPLAY_EVENT_CONNECTION,
+ CREATE_DISPLAY,
+ GET_BUILT_IN_DISPLAY,
+ SET_TRANSACTION_STATE,
+ AUTHENTICATE_SURFACE,
+ CAPTURE_SCREEN,
BLANK,
UNBLANK,
+ GET_DISPLAY_INFO,
CONNECT_DISPLAY,
};
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index b058b8d..5776038 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -59,6 +59,13 @@
// Forcibly remove connection before all references have gone away.
void dispose();
+ // callback when the composer is dies
+ status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient,
+ void* cookie = NULL, uint32_t flags = 0);
+
+ // Get information about a display
+ static status_t getDisplayInfo(DisplayID dpy, DisplayInfo* info);
+
// ------------------------------------------------------------------------
// surface creation / destruction
@@ -80,13 +87,14 @@
uint32_t flags = 0 // usage flags
);
+ static sp<IBinder> createDisplay();
// ------------------------------------------------------------------------
// Composer parameters
// All composer parameters must be changed within a transaction
// several surfaces can be updated in one transaction, all changes are
// committed at once when the transaction is closed.
- // closeGlobalTransaction() usually requires an IPC with the server.
+ // closeGlobalTransaction() requires an IPC with the server.
//! Open a composer transaction on all active SurfaceComposerClients.
static void openGlobalTransaction();
@@ -97,12 +105,6 @@
//! Set the orientation of the given display
static int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
- // Get information about a display
- static status_t getDisplayInfo(DisplayID dpy, DisplayInfo* info);
-
- status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient,
- void* cookie = NULL, uint32_t flags = 0);
-
status_t hide(SurfaceID id);
status_t show(SurfaceID id, int32_t layer = -1);
status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask);
@@ -116,6 +118,16 @@
status_t setLayerStack(SurfaceID id, uint32_t layerStack);
status_t destroySurface(SurfaceID sid);
+ static void setDisplaySurface(const sp<IBinder>& token,
+ const sp<ISurfaceTexture>& surface);
+ static void setDisplayLayerStack(const sp<IBinder>& token,
+ uint32_t layerStack);
+ static void setDisplayOrientation(const sp<IBinder>& token,
+ uint32_t orientation);
+ static void setDisplayViewport(const sp<IBinder>& token,
+ const Rect& viewport);
+ static void setDisplayFrame(const sp<IBinder>& token, const Rect& frame);
+
private:
virtual void onFirstRef();
Composer& getComposer();
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 90e74a9..9765e28 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -106,14 +106,21 @@
eOrientationSwapMask = 0x01
};
- int32_t displayId;
+ enum {
+ eSurfaceChanged = 0x1,
+ eLayerStackChanged = 0x2,
+ eTransformChanged = 0x4
+ };
+
+ uint32_t what;
+ sp<IBinder> token;
sp<ISurfaceTexture> surface;
- uint32_t layerStack;
- uint32_t orientation;
- Rect viewport;
- Rect frame;
- status_t write(Parcel& output) const;
- status_t read(const Parcel& input);
+ uint32_t layerStack;
+ uint32_t orientation;
+ Rect viewport;
+ Rect frame;
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
};
}; // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5d8f1a1..76b23f3 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -179,6 +179,23 @@
return result;
}
+ virtual sp<IBinder> createDisplay()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply);
+ return reply.readStrongBinder();
+ }
+
+ virtual sp<IBinder> getBuiltInDisplay(int32_t id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeInt32(id);
+ remote()->transact(BnSurfaceComposer::GET_BUILT_IN_DISPLAY, data, &reply);
+ return reply.readStrongBinder();
+ }
+
virtual void blank()
{
Parcel data, reply;
@@ -286,6 +303,19 @@
reply->writeStrongBinder(connection->asBinder());
return NO_ERROR;
} break;
+ case CREATE_DISPLAY: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display(createDisplay());
+ reply->writeStrongBinder(display);
+ return NO_ERROR;
+ } break;
+ case GET_BUILT_IN_DISPLAY: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ int32_t id = data.readInt32();
+ sp<IBinder> display(getBuiltInDisplay(id));
+ reply->writeStrongBinder(display);
+ return NO_ERROR;
+ } break;
case BLANK: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
blank();
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 25c773c..07f62c4 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -72,8 +72,9 @@
status_t DisplayState::write(Parcel& output) const {
+ output.writeStrongBinder(token);
output.writeStrongBinder(surface->asBinder());
- output.writeInt32(displayId);
+ output.writeInt32(what);
output.writeInt32(layerStack);
output.writeInt32(orientation);
memcpy(output.writeInplace(sizeof(Rect)), &viewport, sizeof(Rect));
@@ -82,8 +83,9 @@
}
status_t DisplayState::read(const Parcel& input) {
+ token = input.readStrongBinder();
surface = interface_cast<ISurfaceTexture>(input.readStrongBinder());
- displayId = input.readInt32();
+ what = input.readInt32();
layerStack = input.readInt32();
orientation = input.readInt32();
memcpy(&viewport, input.readInplace(sizeof(Rect)), sizeof(Rect));
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7f42a34..db86d4a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -56,16 +56,10 @@
return ComposerService::getInstance().mComposerService;
}
-static inline sp<ISurfaceComposer> getComposerService() {
- return ComposerService::getComposerService();
-}
-
// ---------------------------------------------------------------------------
-// NOTE: this is NOT a member function (it's a friend defined with its
-// declaration).
static inline
-int compare_type( const ComposerState& lhs, const ComposerState& rhs) {
+int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
if (lhs.client < rhs.client) return -1;
if (lhs.client > rhs.client) return 1;
if (lhs.state.surface < rhs.state.surface) return -1;
@@ -73,17 +67,21 @@
return 0;
}
+static inline
+int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
+ return compare_type(lhs.token, rhs.token);
+}
+
class Composer : public Singleton<Composer>
{
friend class Singleton<Composer>;
mutable Mutex mLock;
- SortedVector<ComposerState> mStates;
- int mOrientation;
+ SortedVector<ComposerState> mComposerStates;
+ SortedVector<DisplayState > mDisplayStates;
uint32_t mForceSynchronous;
Composer() : Singleton<Composer>(),
- mOrientation(DisplayState::eOrientationUnchanged),
mForceSynchronous(0)
{ }
@@ -92,7 +90,10 @@
layer_state_t* getLayerStateLocked(
const sp<SurfaceComposerClient>& client, SurfaceID id);
+ DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
+
public:
+ sp<IBinder> createDisplay();
status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
float x, float y);
@@ -115,6 +116,12 @@
status_t setLayerStack(const sp<SurfaceComposerClient>& client,
SurfaceID id, uint32_t layerStack);
+ void setDisplaySurface(const sp<IBinder>& token, const sp<ISurfaceTexture>& surface);
+ void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
+ void setDisplayOrientation(const sp<IBinder>& token, uint32_t orientation);
+ void setDisplayViewport(const sp<IBinder>& token, const Rect& viewport);
+ void setDisplayFrame(const sp<IBinder>& token, const Rect& frame);
+
static void closeGlobalTransaction(bool synchronous) {
Composer::getInstance().closeGlobalTransactionImpl(synchronous);
}
@@ -124,8 +131,12 @@
// ---------------------------------------------------------------------------
+sp<IBinder> Composer::createDisplay() {
+ return ComposerService::getComposerService()->createDisplay();
+}
+
void Composer::closeGlobalTransactionImpl(bool synchronous) {
- sp<ISurfaceComposer> sm(getComposerService());
+ sp<ISurfaceComposer> sm(ComposerService::getComposerService());
Vector<ComposerState> transaction;
Vector<DisplayState> displayTransaction;
@@ -133,15 +144,11 @@
{ // scope for the lock
Mutex::Autolock _l(mLock);
- transaction = mStates;
- mStates.clear();
+ transaction = mComposerStates;
+ mComposerStates.clear();
- // FIXME: this should be the displays transaction state here
- DisplayState item;
- item.orientation = mOrientation;
- displayTransaction.add(item);
-
- mOrientation = DisplayState::eOrientationUnchanged;
+ displayTransaction = mDisplayStates;
+ mDisplayStates.clear();
if (synchronous || mForceSynchronous) {
flags |= ISurfaceComposer::eSynchronous;
@@ -159,13 +166,13 @@
s.client = client->mClient;
s.state.surface = id;
- ssize_t index = mStates.indexOf(s);
+ ssize_t index = mComposerStates.indexOf(s);
if (index < 0) {
// we don't have it, add an initialized layer_state to our list
- index = mStates.add(s);
+ index = mComposerStates.add(s);
}
- ComposerState* const out = mStates.editArray();
+ ComposerState* const out = mComposerStates.editArray();
return &(out[index].state);
}
@@ -273,16 +280,6 @@
return NO_ERROR;
}
-status_t Composer::setOrientation(int orientation) {
- Mutex::Autolock _l(mLock);
- mOrientation = orientation;
-
- // Changing the orientation makes the transaction synchronous.
- mForceSynchronous = true;
-
- return NO_ERROR;
-}
-
status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
SurfaceID id, const Rect& crop) {
Mutex::Autolock _l(mLock);
@@ -296,13 +293,76 @@
// ---------------------------------------------------------------------------
+DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
+ DisplayState s;
+ s.token = token;
+ ssize_t index = mDisplayStates.indexOf(s);
+ if (index < 0) {
+ // we don't have it, add an initialized layer_state to our list
+ s.what = 0;
+ index = mDisplayStates.add(s);
+ }
+ return mDisplayStates.editItemAt(index);
+}
+
+void Composer::setDisplaySurface(const sp<IBinder>& token,
+ const sp<ISurfaceTexture>& surface) {
+ Mutex::Autolock _l(mLock);
+ DisplayState& s(getDisplayStateLocked(token));
+ s.surface = surface;
+ s.what |= DisplayState::eSurfaceChanged;
+}
+
+void Composer::setDisplayLayerStack(const sp<IBinder>& token,
+ uint32_t layerStack) {
+ Mutex::Autolock _l(mLock);
+ DisplayState& s(getDisplayStateLocked(token));
+ s.layerStack = layerStack;
+ s.what |= DisplayState::eLayerStackChanged;
+}
+
+void Composer::setDisplayOrientation(const sp<IBinder>& token,
+ uint32_t orientation) {
+ Mutex::Autolock _l(mLock);
+ DisplayState& s(getDisplayStateLocked(token));
+ s.orientation = orientation;
+ s.what |= DisplayState::eTransformChanged;
+ mForceSynchronous = true; // TODO: do we actually still need this?
+}
+
+// FIXME: get rid of this eventually
+status_t Composer::setOrientation(int orientation) {
+ sp<ISurfaceComposer> sm(ComposerService::getComposerService());
+ sp<IBinder> token(sm->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ Composer::setDisplayOrientation(token, orientation);
+ return NO_ERROR;
+}
+
+void Composer::setDisplayViewport(const sp<IBinder>& token,
+ const Rect& viewport) {
+ Mutex::Autolock _l(mLock);
+ DisplayState& s(getDisplayStateLocked(token));
+ s.viewport = viewport;
+ s.what |= DisplayState::eTransformChanged;
+}
+
+void Composer::setDisplayFrame(const sp<IBinder>& token,
+ const Rect& frame) {
+ Mutex::Autolock _l(mLock);
+ DisplayState& s(getDisplayStateLocked(token));
+ s.frame = frame;
+ s.what |= DisplayState::eTransformChanged;
+}
+
+// ---------------------------------------------------------------------------
+
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}
void SurfaceComposerClient::onFirstRef() {
- sp<ISurfaceComposer> sm(getComposerService());
+ sp<ISurfaceComposer> sm(ComposerService::getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();
if (conn != 0) {
@@ -327,7 +387,7 @@
status_t SurfaceComposerClient::linkToComposerDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
- sp<ISurfaceComposer> sm(getComposerService());
+ sp<ISurfaceComposer> sm(ComposerService::getComposerService());
return sm->asBinder()->linkToDeath(recipient, cookie, flags);
}
@@ -379,6 +439,10 @@
return result;
}
+sp<IBinder> SurfaceComposerClient::createDisplay() {
+ return Composer::getInstance().createDisplay();
+}
+
status_t SurfaceComposerClient::destroySurface(SurfaceID sid) {
if (mStatus != NO_ERROR)
return mStatus;
@@ -461,10 +525,37 @@
// ----------------------------------------------------------------------------
+void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
+ const sp<ISurfaceTexture>& surface) {
+ Composer::getInstance().setDisplaySurface(token, surface);
+}
+
+void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token,
+ uint32_t layerStack) {
+ Composer::getInstance().setDisplayLayerStack(token, layerStack);
+}
+
+void SurfaceComposerClient::setDisplayOrientation(const sp<IBinder>& token,
+ uint32_t orientation) {
+ Composer::getInstance().setDisplayOrientation(token, orientation);
+}
+
+void SurfaceComposerClient::setDisplayViewport(const sp<IBinder>& token,
+ const Rect& viewport) {
+ Composer::getInstance().setDisplayViewport(token, viewport);
+}
+
+void SurfaceComposerClient::setDisplayFrame(const sp<IBinder>& token,
+ const Rect& frame) {
+ Composer::getInstance().setDisplayFrame(token, frame);
+}
+
+// ----------------------------------------------------------------------------
+
status_t SurfaceComposerClient::getDisplayInfo(
DisplayID dpy, DisplayInfo* info)
{
- return getComposerService()->getDisplayInfo(dpy, info);
+ return ComposerService::getComposerService()->getDisplayInfo(dpy, info);
}
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index cb8fe2f..0229dad 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -51,7 +51,8 @@
enum {
DISPLAY_ID_MAIN = 0,
- DISPLAY_ID_HDMI = 1
+ DISPLAY_ID_HDMI = 1,
+ DISPLAY_ID_COUNT
};
enum {
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) {
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index da417ff..6438bee 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -78,7 +78,10 @@
// ---------------------------------------------------------------------------
enum {
- eTransactionNeeded = 0x01, eTraversalNeeded = 0x02
+ eTransactionNeeded = 0x01,
+ eTraversalNeeded = 0x02,
+ eDisplayTransactionNeeded = 0x04,
+ eTransactionMask = 0x07
};
class SurfaceFlinger : public BinderService<SurfaceFlinger>,
@@ -158,19 +161,18 @@
struct DisplayDeviceState {
DisplayDeviceState();
+ DisplayDeviceState(int32_t id);
int32_t id;
+ sp<ISurfaceTexture> surface;
uint32_t layerStack;
Rect viewport;
Rect frame;
uint8_t orientation;
- inline bool operator < (const DisplayDeviceState& rhs) const {
- return id < rhs.id;
- }
};
struct State {
LayerVector layersSortedByZ;
- KeyedVector<int32_t, DisplayDeviceState> displays;
+ DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
};
/* ------------------------------------------------------------------------
@@ -185,6 +187,8 @@
*/
virtual sp<ISurfaceComposerClient> createConnection();
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
+ virtual sp<IBinder> createDisplay();
+ virtual sp<IBinder> getBuiltInDisplay(int32_t id);
virtual void setTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags);
virtual void bootFinished();
@@ -256,6 +260,7 @@
void commitTransaction();
uint32_t setClientStateLocked(const sp<Client>& client,
const layer_state_t& s);
+ uint32_t setDisplayStateLocked(const DisplayState& s);
/* ------------------------------------------------------------------------
* Layer management
@@ -391,6 +396,7 @@
EGLContext mEGLContext;
EGLConfig mEGLConfig;
EGLDisplay mEGLDisplay;
+ sp<IBinder> mDefaultDisplays[DisplayDevice::DISPLAY_ID_COUNT];
// Can only accessed from the main thread, these members
// don't need synchronization