|  | /* | 
|  | * Copyright (C) 2007 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #define LOG_TAG "Surface" | 
|  |  | 
|  | #include <stdint.h> | 
|  | #include <unistd.h> | 
|  | #include <fcntl.h> | 
|  | #include <errno.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/stat.h> | 
|  |  | 
|  | #include <utils/Atomic.h> | 
|  | #include <utils/Errors.h> | 
|  | #include <utils/threads.h> | 
|  | #include <binder/IPCThreadState.h> | 
|  | #include <binder/IMemory.h> | 
|  | #include <utils/Log.h> | 
|  |  | 
|  | #include <ui/ISurface.h> | 
|  | #include <ui/Surface.h> | 
|  | #include <ui/SurfaceComposerClient.h> | 
|  | #include <ui/Rect.h> | 
|  |  | 
|  | #include <private/ui/SharedState.h> | 
|  | #include <private/ui/LayerState.h> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | // --------------------------------------------------------------------------- | 
|  |  | 
|  | Surface::Surface(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) | 
|  | { | 
|  | mSwapRectangle.makeInvalid(); | 
|  | mSurfaceHeapBase[0] = 0; | 
|  | mSurfaceHeapBase[1] = 0; | 
|  | mHeap[0] = data.heap[0]; | 
|  | mHeap[1] = data.heap[1]; | 
|  | } | 
|  |  | 
|  | Surface::Surface(Surface const* rhs) | 
|  | : mOwner(false) | 
|  | { | 
|  | mToken   = rhs->mToken; | 
|  | mIdentity= rhs->mIdentity; | 
|  | mClient  = rhs->mClient; | 
|  | mSurface = rhs->mSurface; | 
|  | mHeap[0] = rhs->mHeap[0]; | 
|  | mHeap[1] = rhs->mHeap[1]; | 
|  | mFormat  = rhs->mFormat; | 
|  | mFlags   = rhs->mFlags; | 
|  | mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0]; | 
|  | mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1]; | 
|  | mSwapRectangle.makeInvalid(); | 
|  | } | 
|  |  | 
|  | Surface::~Surface() | 
|  | { | 
|  | if (mOwner && mToken>=0 && mClient!=0) { | 
|  | mClient->destroySurface(mToken); | 
|  | } | 
|  | mClient.clear(); | 
|  | mSurface.clear(); | 
|  | mHeap[0].clear(); | 
|  | mHeap[1].clear(); | 
|  | IPCThreadState::self()->flushCommands(); | 
|  | } | 
|  |  | 
|  | sp<Surface> Surface::dup() const | 
|  | { | 
|  | Surface const * r = this; | 
|  | if (this && mOwner) { | 
|  | // the only reason we need to do this is because of Java's garbage | 
|  | // collector: because we're creating a copy of the Surface | 
|  | // instead of a reference, we can garantee that when our last | 
|  | // reference goes away, the real surface will be deleted. | 
|  | // Without this hack (the code is correct too), we'd have to | 
|  | // wait for a GC for the surface to go away. | 
|  | r = new Surface(this); | 
|  | } | 
|  | return const_cast<Surface*>(r); | 
|  | } | 
|  |  | 
|  | status_t Surface::nextBuffer(SurfaceInfo* info) { | 
|  | return mClient->nextBuffer(this, info); | 
|  | } | 
|  |  | 
|  | status_t Surface::lock(SurfaceInfo* info, bool blocking) { | 
|  | return Surface::lock(info, NULL, blocking); | 
|  | } | 
|  |  | 
|  | status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) { | 
|  | if (heapBase(0) == 0) return INVALID_OPERATION; | 
|  | if (heapBase(1) == 0) return INVALID_OPERATION; | 
|  | return mClient->lockSurface(this, info, dirty, blocking); | 
|  | } | 
|  |  | 
|  | status_t Surface::unlockAndPost() { | 
|  | if (heapBase(0) == 0) return INVALID_OPERATION; | 
|  | if (heapBase(1) == 0) return INVALID_OPERATION; | 
|  | return mClient->unlockAndPostSurface(this); | 
|  | } | 
|  |  | 
|  | status_t Surface::unlock() { | 
|  | if (heapBase(0) == 0) return INVALID_OPERATION; | 
|  | if (heapBase(1) == 0) return INVALID_OPERATION; | 
|  | return mClient->unlockSurface(this); | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  | void Surface::setDirtyRegion(const Region& region) const { | 
|  | mDirtyRegion = region; | 
|  | } | 
|  | const Rect& Surface::swapRectangle() const { | 
|  | return mSwapRectangle; | 
|  | } | 
|  | void Surface::setSwapRectangle(const Rect& r) { | 
|  | mSwapRectangle = r; | 
|  | } | 
|  |  | 
|  | sp<Surface> Surface::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.heap[0]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); | 
|  | data.heap[1]            = interface_cast<IMemoryHeap>(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 Surface(client, surface, data, 0, 0, format, flags, false); | 
|  | } | 
|  |  | 
|  | status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel) | 
|  | { | 
|  | uint32_t flags=0; | 
|  | uint32_t format=0; | 
|  | SurfaceID token = -1; | 
|  | uint32_t identity = 0; | 
|  | sp<SurfaceComposerClient> client; | 
|  | sp<ISurface> sur; | 
|  | sp<IMemoryHeap> heap[2]; | 
|  | if (surface->isValid()) { | 
|  | token = surface->mToken; | 
|  | identity = surface->mIdentity; | 
|  | client = surface->mClient; | 
|  | sur = surface->mSurface; | 
|  | heap[0] = surface->mHeap[0]; | 
|  | heap[1] = surface->mHeap[1]; | 
|  | format = surface->mFormat; | 
|  | flags = surface->mFlags; | 
|  | } | 
|  | parcel->writeStrongBinder(client!=0  ? client->connection() : NULL); | 
|  | parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL); | 
|  | parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder()  : NULL); | 
|  | parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder()  : NULL); | 
|  | parcel->writeInt32(token); | 
|  | parcel->writeInt32(identity); | 
|  | parcel->writeInt32(format); | 
|  | parcel->writeInt32(flags); | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) | 
|  | { | 
|  | if (lhs == 0 || rhs == 0) | 
|  | return false; | 
|  | return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); | 
|  | } | 
|  |  | 
|  | void* Surface::heapBase(int i) const | 
|  | { | 
|  | void* heapBase = mSurfaceHeapBase[i]; | 
|  | // map lazily so it doesn't get mapped in clients that don't need it | 
|  | if (heapBase == 0) { | 
|  | const sp<IMemoryHeap>& heap(mHeap[i]); | 
|  | if (heap != 0) { | 
|  | heapBase = static_cast<uint8_t*>(heap->base()); | 
|  | if (heapBase == MAP_FAILED) { | 
|  | heapBase = NULL; | 
|  | LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)", | 
|  | heap->asBinder().get(), heap.get()); | 
|  | } | 
|  | mSurfaceHeapBase[i] = heapBase; | 
|  | } | 
|  | } | 
|  | return heapBase; | 
|  | } | 
|  |  | 
|  | }; // namespace android | 
|  |  |