summaryrefslogtreecommitdiff
path: root/libs/ui/Surface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ui/Surface.cpp')
-rw-r--r--libs/ui/Surface.cpp313
1 files changed, 255 insertions, 58 deletions
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 51abd95faa05..63699c7fd7b1 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -143,6 +143,216 @@ static void copyBlt(const android_native_buffer_t* dst,
}
}
+
+// ============================================================================
+// SurfaceControl
+// ============================================================================
+
+
+SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client,
+ const sp<ISurface>& surface,
+ const ISurfaceFlingerClient::surface_data_t& data,
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+ bool owner)
+ : mClient(client), mSurface(surface),
+ mToken(data.token), mIdentity(data.identity),
+ mFormat(format), mFlags(flags), mOwner(owner)
+{
+}
+
+SurfaceControl::~SurfaceControl()
+{
+ destroy();
+}
+
+void SurfaceControl::destroy()
+{
+ // Destroy the surface in SurfaceFlinger if we were the owner
+ // (in any case, a client won't be able to, because it won't have the
+ // right permission).
+ if (mOwner && mToken>=0 && mClient!=0) {
+ mClient->destroySurface(mToken);
+ }
+
+ // clear all references and trigger an IPC now, to make sure things
+ // happen without delay, since these resources are quite heavy.
+ mClient.clear();
+ mSurface.clear();
+ IPCThreadState::self()->flushCommands();
+}
+
+void SurfaceControl::clear()
+{
+ // here, the window manager tells us explicitly that we should destroy
+ // the surface's resource. Soon after this call, it will also release
+ // its last reference (which will call the dtor); however, it is possible
+ // that a client living in the same process still holds references which
+ // would delay the call to the dtor -- that is why we need this explicit
+ // "clear()" call.
+ destroy();
+}
+
+status_t SurfaceControl::setLayer(int32_t layer) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setLayer(mToken, layer);
+}
+status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setPosition(mToken, x, y);
+}
+status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setSize(mToken, w, h);
+}
+status_t SurfaceControl::hide() {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->hide(mToken);
+}
+status_t SurfaceControl::show(int32_t layer) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->show(mToken, layer);
+}
+status_t SurfaceControl::freeze() {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->freeze(mToken);
+}
+status_t SurfaceControl::unfreeze() {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->unfreeze(mToken);
+}
+status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setFlags(mToken, flags, mask);
+}
+status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setTransparentRegionHint(mToken, transparent);
+}
+status_t SurfaceControl::setAlpha(float alpha) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setAlpha(mToken, alpha);
+}
+status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
+}
+status_t SurfaceControl::setFreezeTint(uint32_t tint) {
+ const sp<SurfaceComposerClient>& client(mClient);
+ if (client == 0) return INVALID_OPERATION;
+ status_t err = validate(client->mControl);
+ if (err < 0) return err;
+ return client->setFreezeTint(mToken, tint);
+}
+
+sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel)
+{
+ sp<SurfaceComposerClient> client;
+ ISurfaceFlingerClient::surface_data_t data;
+ sp<IBinder> clientBinder= parcel->readStrongBinder();
+ sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
+ data.token = parcel->readInt32();
+ data.identity = parcel->readInt32();
+ PixelFormat format = parcel->readInt32();
+ uint32_t flags = parcel->readInt32();
+
+ if (clientBinder != NULL)
+ client = SurfaceComposerClient::clientForConnection(clientBinder);
+
+ return new SurfaceControl(client, surface, data, 0, 0, format, flags, false);
+}
+
+status_t SurfaceControl::writeToParcel(const sp<SurfaceControl>& surface, Parcel* parcel)
+{
+ uint32_t flags=0;
+ uint32_t format=0;
+ SurfaceID token = -1;
+ uint32_t identity = 0;
+ sp<SurfaceComposerClient> client;
+ sp<ISurface> sur;
+ if (SurfaceControl::isValid(surface)) {
+ token = surface->mToken;
+ identity = surface->mIdentity;
+ client = surface->mClient;
+ sur = surface->mSurface;
+ format = surface->mFormat;
+ flags = surface->mFlags;
+ }
+ parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
+ parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+ parcel->writeInt32(token);
+ parcel->writeInt32(identity);
+ parcel->writeInt32(format);
+ parcel->writeInt32(flags);
+ return NO_ERROR;
+}
+
+bool SurfaceControl::isSameSurface(
+ const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
+{
+ if (lhs == 0 || rhs == 0)
+ return false;
+ return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
+}
+
+
+status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
+{
+ if (mToken<0 || mClient==0) {
+ LOGE("invalid token (%d, identity=%u) or client (%p)",
+ mToken, mIdentity, mClient.get());
+ return NO_INIT;
+ }
+ if (cblk == 0) {
+ LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+ return NO_INIT;
+ }
+ status_t err = cblk->validate(mToken);
+ if (err != NO_ERROR) {
+ LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+ mToken, mIdentity, err, strerror(-err));
+ return err;
+ }
+ if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+ LOGE("using an invalid surface id=%d, identity=%u should be %d",
+ mToken, mIdentity, cblk->layers[mToken].identity);
+ return NO_INIT;
+ }
+ return NO_ERROR;
+}
+
// ============================================================================
// Surface
// ============================================================================
@@ -156,6 +366,9 @@ Surface::Surface(const sp<SurfaceComposerClient>& client,
mToken(data.token), mIdentity(data.identity),
mFormat(format), mFlags(flags), mOwner(owner)
{
+ mSurfaceControl = new SurfaceControl(
+ client, surface, data, w, h, format, flags, owner);
+
android_native_window_t::connect = connect;
android_native_window_t::disconnect = disconnect;
android_native_window_t::setSwapInterval = setSwapInterval;
@@ -191,12 +404,7 @@ Surface::~Surface()
void Surface::destroy()
{
- // Destroy the surface in SurfaceFlinger if we were the owner
- // (in any case, a client won't be able to, because it won't have the
- // right permission).
- if (mOwner && mToken>=0 && mClient!=0) {
- mClient->destroySurface(mToken);
- }
+ mSurfaceControl->destroy();
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
@@ -207,20 +415,7 @@ void Surface::destroy()
void Surface::clear()
{
- // here, the window manager tells us explicitly that we should destroy
- // the surface's resource. Soon after this call, it will also release
- // its last reference (which will call the dtor); however, it is possible
- // that a client living in the same process still holds references which
- // would delay the call to the dtor -- that is why we need this explicit
- // "clear()" call.
-
- // FIXME: we should probably unmap the buffers here. The problem is that
- // the app could be in the middle of using them, and if we don't unmap now
- // and we're in the system process, the mapping will be lost (because
- // the buffer will be freed, and the handles destroyed)
-
- Mutex::Autolock _l(mSurfaceLock);
- destroy();
+ mSurfaceControl->clear();
}
status_t Surface::validate(per_client_cblk_t const* cblk) const
@@ -473,44 +668,6 @@ void Surface::_send_dirty_region(
}
}
-
-status_t Surface::setLayer(int32_t layer) {
- return mClient->setLayer(this, layer);
-}
-status_t Surface::setPosition(int32_t x, int32_t y) {
- return mClient->setPosition(this, x, y);
-}
-status_t Surface::setSize(uint32_t w, uint32_t h) {
- return mClient->setSize(this, w, h);
-}
-status_t Surface::hide() {
- return mClient->hide(this);
-}
-status_t Surface::show(int32_t layer) {
- return mClient->show(this, layer);
-}
-status_t Surface::freeze() {
- return mClient->freeze(this);
-}
-status_t Surface::unfreeze() {
- return mClient->unfreeze(this);
-}
-status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
- return mClient->setFlags(this, flags, mask);
-}
-status_t Surface::setTransparentRegionHint(const Region& transparent) {
- return mClient->setTransparentRegionHint(this, transparent);
-}
-status_t Surface::setAlpha(float alpha) {
- return mClient->setAlpha(this, alpha);
-}
-status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
- return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
-}
-status_t Surface::setFreezeTint(uint32_t tint) {
- return mClient->setFreezeTint(this, tint);
-}
-
Region Surface::dirtyRegion() const {
return mDirtyRegion;
}
@@ -593,5 +750,45 @@ status_t Surface::getBufferLocked(int index)
return err;
}
+
+
+status_t Surface::setLayer(int32_t layer) {
+ return mSurfaceControl->setLayer(layer);
+}
+status_t Surface::setPosition(int32_t x, int32_t y) {
+ return mSurfaceControl->setPosition(x, y);
+}
+status_t Surface::setSize(uint32_t w, uint32_t h) {
+ return mSurfaceControl->setSize(w, h);
+}
+status_t Surface::hide() {
+ return mSurfaceControl->hide();
+}
+status_t Surface::show(int32_t layer) {
+ return mSurfaceControl->show(layer);
+}
+status_t Surface::freeze() {
+ return mSurfaceControl->freeze();
+}
+status_t Surface::unfreeze() {
+ return mSurfaceControl->unfreeze();
+}
+status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
+ return mSurfaceControl->setFlags(flags, mask);
+}
+status_t Surface::setTransparentRegionHint(const Region& transparent) {
+ return mSurfaceControl->setTransparentRegionHint(transparent);
+}
+status_t Surface::setAlpha(float alpha) {
+ return mSurfaceControl->setAlpha(alpha);
+}
+status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+ return mSurfaceControl->setMatrix(dsdx, dtdx, dsdy, dtdy);
+}
+status_t Surface::setFreezeTint(uint32_t tint) {
+ return mSurfaceControl->setFreezeTint(tint);
+}
+
+
}; // namespace android