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
This commit is contained in:
Mathias Agopian 2012-08-09 16:29:12 -07:00
parent ef7b9c7eac
commit e57f292595
9 changed files with 426 additions and 169 deletions

View File

@ -48,6 +48,11 @@ public:
eSynchronous = 0x01,
};
enum {
eDisplayIdMain = 0,
eDisplayIdHdmi = 1
};
/* create connection with surface flinger, requires
* ACCESS_SURFACE_FLINGER permission
*/
@ -57,6 +62,19 @@ public:
*/
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 @@ public:
*/
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 @@ public:
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 @@ public:
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,
};

View File

@ -59,6 +59,13 @@ public:
// 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 @@ public:
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 @@ public:
//! 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 @@ public:
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();

View File

@ -106,14 +106,21 @@ struct DisplayState {
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

View File

@ -179,6 +179,23 @@ public:
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 @@ status_t BnSurfaceComposer::onTransact(
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();

View File

@ -72,8 +72,9 @@ status_t ComposerState::read(const Parcel& input) {
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::write(Parcel& output) const {
}
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));

View File

@ -56,16 +56,10 @@ sp<ISurfaceComposer> ComposerService::getComposerService() {
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 @@ int compare_type( const ComposerState& lhs, const ComposerState& rhs) {
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 @@ class Composer : public Singleton<Composer>
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 @@ public:
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 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer);
// ---------------------------------------------------------------------------
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 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) {
{ // 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 @@ layer_state_t* Composer::getLayerStateLocked(
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 @@ status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
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 @@ status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
// ---------------------------------------------------------------------------
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 @@ sp<IBinder> SurfaceComposerClient::connection() const {
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 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
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 @@ status_t SurfaceComposerClient::setOrientation(DisplayID dpy,
// ----------------------------------------------------------------------------
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);
}
// ----------------------------------------------------------------------------

View File

@ -51,7 +51,8 @@ public:
enum {
DISPLAY_ID_MAIN = 0,
DISPLAY_ID_HDMI = 1
DISPLAY_ID_HDMI = 1,
DISPLAY_ID_COUNT
};
enum {

View File

@ -161,6 +161,39 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
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 @@ status_t SurfaceFlinger::readyToRun()
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 @@ status_t SurfaceFlinger::readyToRun()
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::onMessageReceived(int32_t what) {
}
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 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
// 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 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
* 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 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// 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 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
}
} 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 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// 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 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
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 @@ void SurfaceFlinger::setTransactionState(
}
}
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 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer)
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 @@ status_t SurfaceFlinger::onTransact(
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 @@ int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
// ---------------------------------------------------------------------------
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) {
}
// ---------------------------------------------------------------------------

View File

@ -78,7 +78,10 @@ public:
// ---------------------------------------------------------------------------
enum {
eTransactionNeeded = 0x01, eTraversalNeeded = 0x02
eTransactionNeeded = 0x01,
eTraversalNeeded = 0x02,
eDisplayTransactionNeeded = 0x04,
eTransactionMask = 0x07
};
class SurfaceFlinger : public BinderService<SurfaceFlinger>,
@ -158,19 +161,18 @@ private:
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 @@ private:
*/
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 @@ private:
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 @@ private:
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