Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "Surface"
     18 
     19 #include <stdint.h>
     20 #include <errno.h>
     21 #include <sys/types.h>
     22 #include <sys/stat.h>
     23 
     24 #include <utils/CallStack.h>
     25 #include <utils/Errors.h>
     26 #include <utils/Log.h>
     27 #include <utils/threads.h>
     28 
     29 #include <binder/IPCThreadState.h>
     30 
     31 #include <gui/SurfaceTextureClient.h>
     32 
     33 #include <ui/DisplayInfo.h>
     34 #include <ui/GraphicBuffer.h>
     35 #include <ui/Rect.h>
     36 
     37 #include <surfaceflinger/ISurface.h>
     38 #include <surfaceflinger/ISurfaceComposer.h>
     39 #include <surfaceflinger/Surface.h>
     40 #include <surfaceflinger/SurfaceComposerClient.h>
     41 
     42 namespace android {
     43 
     44 // ============================================================================
     45 //  SurfaceControl
     46 // ============================================================================
     47 
     48 SurfaceControl::SurfaceControl(
     49         const sp<SurfaceComposerClient>& client,
     50         const sp<ISurface>& surface,
     51         const ISurfaceComposerClient::surface_data_t& data)
     52     : mClient(client), mSurface(surface),
     53       mToken(data.token), mIdentity(data.identity)
     54 {
     55 }
     56 
     57 SurfaceControl::~SurfaceControl()
     58 {
     59     destroy();
     60 }
     61 
     62 void SurfaceControl::destroy()
     63 {
     64     if (isValid()) {
     65         mClient->destroySurface(mToken);
     66     }
     67 
     68     // clear all references and trigger an IPC now, to make sure things
     69     // happen without delay, since these resources are quite heavy.
     70     mClient.clear();
     71     mSurface.clear();
     72     IPCThreadState::self()->flushCommands();
     73 }
     74 
     75 void SurfaceControl::clear()
     76 {
     77     // here, the window manager tells us explicitly that we should destroy
     78     // the surface's resource. Soon after this call, it will also release
     79     // its last reference (which will call the dtor); however, it is possible
     80     // that a client living in the same process still holds references which
     81     // would delay the call to the dtor -- that is why we need this explicit
     82     // "clear()" call.
     83     destroy();
     84 }
     85 
     86 bool SurfaceControl::isSameSurface(
     87         const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
     88 {
     89     if (lhs == 0 || rhs == 0)
     90         return false;
     91     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
     92 }
     93 
     94 status_t SurfaceControl::setLayer(int32_t layer) {
     95     status_t err = validate();
     96     if (err < 0) return err;
     97     const sp<SurfaceComposerClient>& client(mClient);
     98     return client->setLayer(mToken, layer);
     99 }
    100 status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
    101     status_t err = validate();
    102     if (err < 0) return err;
    103     const sp<SurfaceComposerClient>& client(mClient);
    104     return client->setPosition(mToken, x, y);
    105 }
    106 status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
    107     status_t err = validate();
    108     if (err < 0) return err;
    109     const sp<SurfaceComposerClient>& client(mClient);
    110     return client->setSize(mToken, w, h);
    111 }
    112 status_t SurfaceControl::hide() {
    113     status_t err = validate();
    114     if (err < 0) return err;
    115     const sp<SurfaceComposerClient>& client(mClient);
    116     return client->hide(mToken);
    117 }
    118 status_t SurfaceControl::show(int32_t layer) {
    119     status_t err = validate();
    120     if (err < 0) return err;
    121     const sp<SurfaceComposerClient>& client(mClient);
    122     return client->show(mToken, layer);
    123 }
    124 status_t SurfaceControl::freeze() {
    125     status_t err = validate();
    126     if (err < 0) return err;
    127     const sp<SurfaceComposerClient>& client(mClient);
    128     return client->freeze(mToken);
    129 }
    130 status_t SurfaceControl::unfreeze() {
    131     status_t err = validate();
    132     if (err < 0) return err;
    133     const sp<SurfaceComposerClient>& client(mClient);
    134     return client->unfreeze(mToken);
    135 }
    136 status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
    137     status_t err = validate();
    138     if (err < 0) return err;
    139     const sp<SurfaceComposerClient>& client(mClient);
    140     return client->setFlags(mToken, flags, mask);
    141 }
    142 status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
    143     status_t err = validate();
    144     if (err < 0) return err;
    145     const sp<SurfaceComposerClient>& client(mClient);
    146     return client->setTransparentRegionHint(mToken, transparent);
    147 }
    148 status_t SurfaceControl::setAlpha(float alpha) {
    149     status_t err = validate();
    150     if (err < 0) return err;
    151     const sp<SurfaceComposerClient>& client(mClient);
    152     return client->setAlpha(mToken, alpha);
    153 }
    154 status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    155     status_t err = validate();
    156     if (err < 0) return err;
    157     const sp<SurfaceComposerClient>& client(mClient);
    158     return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
    159 }
    160 status_t SurfaceControl::setFreezeTint(uint32_t tint) {
    161     status_t err = validate();
    162     if (err < 0) return err;
    163     const sp<SurfaceComposerClient>& client(mClient);
    164     return client->setFreezeTint(mToken, tint);
    165 }
    166 
    167 status_t SurfaceControl::validate() const
    168 {
    169     if (mToken<0 || mClient==0) {
    170         LOGE("invalid token (%d, identity=%u) or client (%p)",
    171                 mToken, mIdentity, mClient.get());
    172         return NO_INIT;
    173     }
    174     return NO_ERROR;
    175 }
    176 
    177 status_t SurfaceControl::writeSurfaceToParcel(
    178         const sp<SurfaceControl>& control, Parcel* parcel)
    179 {
    180     sp<ISurface> sur;
    181     uint32_t identity = 0;
    182     if (SurfaceControl::isValid(control)) {
    183         sur      = control->mSurface;
    184         identity = control->mIdentity;
    185     }
    186     parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
    187     parcel->writeStrongBinder(NULL);  // NULL ISurfaceTexture in this case.
    188     parcel->writeInt32(identity);
    189     return NO_ERROR;
    190 }
    191 
    192 sp<Surface> SurfaceControl::getSurface() const
    193 {
    194     Mutex::Autolock _l(mLock);
    195     if (mSurfaceData == 0) {
    196         sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this));
    197         mSurfaceData = new Surface(surface_control);
    198     }
    199     return mSurfaceData;
    200 }
    201 
    202 // ============================================================================
    203 //  Surface
    204 // ============================================================================
    205 
    206 // ---------------------------------------------------------------------------
    207 
    208 Surface::Surface(const sp<SurfaceControl>& surface)
    209     : SurfaceTextureClient(),
    210       mSurface(surface->mSurface),
    211       mIdentity(surface->mIdentity)
    212 {
    213     sp<ISurfaceTexture> st;
    214     if (mSurface != NULL) {
    215         st = mSurface->getSurfaceTexture();
    216     }
    217     init(st);
    218 }
    219 
    220 Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
    221     : SurfaceTextureClient()
    222 {
    223     mSurface = interface_cast<ISurface>(ref);
    224     sp<IBinder> st_binder(parcel.readStrongBinder());
    225     sp<ISurfaceTexture> st;
    226     if (st_binder != NULL) {
    227         st = interface_cast<ISurfaceTexture>(st_binder);
    228     } else if (mSurface != NULL) {
    229         st = mSurface->getSurfaceTexture();
    230     }
    231 
    232     mIdentity   = parcel.readInt32();
    233     init(st);
    234 }
    235 
    236 Surface::Surface(const sp<ISurfaceTexture>& st)
    237     : SurfaceTextureClient(),
    238       mSurface(NULL),
    239       mIdentity(0)
    240 {
    241     init(st);
    242 }
    243 
    244 status_t Surface::writeToParcel(
    245         const sp<Surface>& surface, Parcel* parcel)
    246 {
    247     sp<ISurface> sur;
    248     sp<ISurfaceTexture> st;
    249     uint32_t identity = 0;
    250     if (Surface::isValid(surface)) {
    251         sur      = surface->mSurface;
    252         st       = surface->getISurfaceTexture();
    253         identity = surface->mIdentity;
    254     } else if (surface != 0 &&
    255             (surface->mSurface != NULL ||
    256              surface->getISurfaceTexture() != NULL)) {
    257         LOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: "
    258              "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ",
    259              surface->mSurface.get(), surface->getISurfaceTexture().get(),
    260              surface->mIdentity);
    261     }
    262 
    263     parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL);
    264     parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL);
    265     parcel->writeInt32(identity);
    266     return NO_ERROR;
    267 
    268 }
    269 
    270 Mutex Surface::sCachedSurfacesLock;
    271 DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
    272 
    273 sp<Surface> Surface::readFromParcel(const Parcel& data) {
    274     Mutex::Autolock _l(sCachedSurfacesLock);
    275     sp<IBinder> binder(data.readStrongBinder());
    276     sp<Surface> surface = sCachedSurfaces.valueFor(binder).promote();
    277     if (surface == 0) {
    278        surface = new Surface(data, binder);
    279        sCachedSurfaces.add(binder, surface);
    280     } else {
    281         // The Surface was found in the cache, but we still should clear any
    282         // remaining data from the parcel.
    283         data.readStrongBinder();  // ISurfaceTexture
    284         data.readInt32();         // identity
    285     }
    286     if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) {
    287         surface = 0;
    288     }
    289     cleanCachedSurfacesLocked();
    290     return surface;
    291 }
    292 
    293 // Remove the stale entries from the surface cache.  This should only be called
    294 // with sCachedSurfacesLock held.
    295 void Surface::cleanCachedSurfacesLocked() {
    296     for (int i = sCachedSurfaces.size()-1; i >= 0; --i) {
    297         wp<Surface> s(sCachedSurfaces.valueAt(i));
    298         if (s == 0 || s.promote() == 0) {
    299             sCachedSurfaces.removeItemsAt(i);
    300         }
    301     }
    302 }
    303 
    304 void Surface::init(const sp<ISurfaceTexture>& surfaceTexture)
    305 {
    306     if (mSurface != NULL || surfaceTexture != NULL) {
    307         LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
    308         if (surfaceTexture != NULL) {
    309             setISurfaceTexture(surfaceTexture);
    310             setUsage(GraphicBuffer::USAGE_HW_RENDER);
    311         }
    312 
    313         DisplayInfo dinfo;
    314         SurfaceComposerClient::getDisplayInfo(0, &dinfo);
    315         const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
    316         const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
    317         const_cast<uint32_t&>(ANativeWindow::flags) = 0;
    318     }
    319 }
    320 
    321 Surface::~Surface()
    322 {
    323     // clear all references and trigger an IPC now, to make sure things
    324     // happen without delay, since these resources are quite heavy.
    325     mSurface.clear();
    326     IPCThreadState::self()->flushCommands();
    327 }
    328 
    329 bool Surface::isValid() {
    330     return getISurfaceTexture() != NULL;
    331 }
    332 
    333 sp<ISurfaceTexture> Surface::getSurfaceTexture() {
    334     return getISurfaceTexture();
    335 }
    336 
    337 sp<IBinder> Surface::asBinder() const {
    338     return mSurface!=0 ? mSurface->asBinder() : 0;
    339 }
    340 
    341 // ----------------------------------------------------------------------------
    342 
    343 int Surface::query(int what, int* value) const {
    344     switch (what) {
    345     case NATIVE_WINDOW_CONCRETE_TYPE:
    346         *value = NATIVE_WINDOW_SURFACE;
    347         return NO_ERROR;
    348     }
    349     return SurfaceTextureClient::query(what, value);
    350 }
    351 
    352 // ----------------------------------------------------------------------------
    353 
    354 status_t Surface::lock(SurfaceInfo* other, Region* inOutDirtyRegion) {
    355     ANativeWindow_Buffer outBuffer;
    356 
    357     ARect temp;
    358     ARect* inOutDirtyBounds = NULL;
    359     if (inOutDirtyRegion) {
    360         temp = inOutDirtyRegion->getBounds();
    361         inOutDirtyBounds = &temp;
    362     }
    363 
    364     status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds);
    365 
    366     if (err == NO_ERROR) {
    367         other->w = uint32_t(outBuffer.width);
    368         other->h = uint32_t(outBuffer.height);
    369         other->s = uint32_t(outBuffer.stride);
    370         other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
    371         other->format = uint32_t(outBuffer.format);
    372         other->bits = outBuffer.bits;
    373     }
    374 
    375     if (inOutDirtyRegion) {
    376         inOutDirtyRegion->set( static_cast<Rect const&>(temp) );
    377     }
    378 
    379     return err;
    380 }
    381 
    382 status_t Surface::unlockAndPost() {
    383     return SurfaceTextureClient::unlockAndPost();
    384 }
    385 
    386 // ----------------------------------------------------------------------------
    387 }; // namespace android
    388