The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 <unistd.h> |
| 21 | #include <fcntl.h> |
| 22 | #include <errno.h> |
| 23 | #include <sys/types.h> |
| 24 | #include <sys/stat.h> |
| 25 | |
| 26 | #include <utils/Atomic.h> |
| 27 | #include <utils/Errors.h> |
| 28 | #include <utils/threads.h> |
| 29 | #include <utils/IPCThreadState.h> |
| 30 | #include <utils/IMemory.h> |
| 31 | #include <utils/Log.h> |
| 32 | |
| 33 | #include <ui/ISurface.h> |
| 34 | #include <ui/Surface.h> |
| 35 | #include <ui/SurfaceComposerClient.h> |
| 36 | #include <ui/Rect.h> |
| 37 | |
| 38 | #include <private/ui/SharedState.h> |
| 39 | #include <private/ui/LayerState.h> |
| 40 | |
| 41 | namespace android { |
| 42 | |
| 43 | // --------------------------------------------------------------------------- |
| 44 | |
| 45 | Surface::Surface(const sp<SurfaceComposerClient>& client, |
| 46 | const sp<ISurface>& surface, |
| 47 | const ISurfaceFlingerClient::surface_data_t& data, |
| 48 | uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, |
| 49 | bool owner) |
| 50 | : mClient(client), mSurface(surface), |
| 51 | mToken(data.token), mIdentity(data.identity), |
| 52 | mFormat(format), mFlags(flags), mOwner(owner) |
| 53 | { |
| 54 | mSwapRectangle.makeInvalid(); |
| 55 | mSurfaceHeapBase[0] = 0; |
| 56 | mSurfaceHeapBase[1] = 0; |
| 57 | mHeap[0] = data.heap[0]; |
| 58 | mHeap[1] = data.heap[1]; |
| 59 | } |
| 60 | |
| 61 | Surface::Surface(Surface const* rhs) |
| 62 | : mOwner(false) |
| 63 | { |
| 64 | mToken = rhs->mToken; |
| 65 | mIdentity= rhs->mIdentity; |
| 66 | mClient = rhs->mClient; |
| 67 | mSurface = rhs->mSurface; |
| 68 | mHeap[0] = rhs->mHeap[0]; |
| 69 | mHeap[1] = rhs->mHeap[1]; |
| 70 | mFormat = rhs->mFormat; |
| 71 | mFlags = rhs->mFlags; |
| 72 | mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0]; |
| 73 | mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1]; |
| 74 | mSwapRectangle.makeInvalid(); |
| 75 | } |
| 76 | |
| 77 | Surface::~Surface() |
| 78 | { |
| 79 | if (mOwner && mToken>=0 && mClient!=0) { |
| 80 | mClient->destroySurface(mToken); |
| 81 | } |
| 82 | mClient.clear(); |
| 83 | mSurface.clear(); |
| 84 | mHeap[0].clear(); |
| 85 | mHeap[1].clear(); |
| 86 | IPCThreadState::self()->flushCommands(); |
| 87 | } |
| 88 | |
| 89 | sp<Surface> Surface::dup() const |
| 90 | { |
| 91 | Surface const * r = this; |
| 92 | if (this && mOwner) { |
| 93 | // the only reason we need to do this is because of Java's garbage |
| 94 | // collector: because we're creating a copy of the Surface |
| 95 | // instead of a reference, we can garantee that when our last |
| 96 | // reference goes away, the real surface will be deleted. |
| 97 | // Without this hack (the code is correct too), we'd have to |
| 98 | // wait for a GC for the surface to go away. |
| 99 | r = new Surface(this); |
| 100 | } |
| 101 | return const_cast<Surface*>(r); |
| 102 | } |
| 103 | |
| 104 | status_t Surface::nextBuffer(SurfaceInfo* info) { |
| 105 | return mClient->nextBuffer(this, info); |
| 106 | } |
| 107 | |
| 108 | status_t Surface::lock(SurfaceInfo* info, bool blocking) { |
| 109 | return Surface::lock(info, NULL, blocking); |
| 110 | } |
| 111 | |
| 112 | status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) { |
| 113 | if (heapBase(0) == 0) return INVALID_OPERATION; |
| 114 | if (heapBase(1) == 0) return INVALID_OPERATION; |
| 115 | return mClient->lockSurface(this, info, dirty, blocking); |
| 116 | } |
| 117 | |
| 118 | status_t Surface::unlockAndPost() { |
| 119 | if (heapBase(0) == 0) return INVALID_OPERATION; |
| 120 | if (heapBase(1) == 0) return INVALID_OPERATION; |
| 121 | return mClient->unlockAndPostSurface(this); |
| 122 | } |
| 123 | |
| 124 | status_t Surface::unlock() { |
| 125 | if (heapBase(0) == 0) return INVALID_OPERATION; |
| 126 | if (heapBase(1) == 0) return INVALID_OPERATION; |
| 127 | return mClient->unlockSurface(this); |
| 128 | } |
| 129 | |
| 130 | status_t Surface::setLayer(int32_t layer) { |
| 131 | return mClient->setLayer(this, layer); |
| 132 | } |
| 133 | status_t Surface::setPosition(int32_t x, int32_t y) { |
| 134 | return mClient->setPosition(this, x, y); |
| 135 | } |
| 136 | status_t Surface::setSize(uint32_t w, uint32_t h) { |
| 137 | return mClient->setSize(this, w, h); |
| 138 | } |
| 139 | status_t Surface::hide() { |
| 140 | return mClient->hide(this); |
| 141 | } |
| 142 | status_t Surface::show(int32_t layer) { |
| 143 | return mClient->show(this, layer); |
| 144 | } |
| 145 | status_t Surface::freeze() { |
| 146 | return mClient->freeze(this); |
| 147 | } |
| 148 | status_t Surface::unfreeze() { |
| 149 | return mClient->unfreeze(this); |
| 150 | } |
| 151 | status_t Surface::setFlags(uint32_t flags, uint32_t mask) { |
| 152 | return mClient->setFlags(this, flags, mask); |
| 153 | } |
| 154 | status_t Surface::setTransparentRegionHint(const Region& transparent) { |
| 155 | return mClient->setTransparentRegionHint(this, transparent); |
| 156 | } |
| 157 | status_t Surface::setAlpha(float alpha) { |
| 158 | return mClient->setAlpha(this, alpha); |
| 159 | } |
| 160 | status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { |
| 161 | return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy); |
| 162 | } |
| 163 | status_t Surface::setFreezeTint(uint32_t tint) { |
| 164 | return mClient->setFreezeTint(this, tint); |
| 165 | } |
| 166 | |
| 167 | Region Surface::dirtyRegion() const { |
| 168 | return mDirtyRegion; |
| 169 | } |
| 170 | void Surface::setDirtyRegion(const Region& region) const { |
| 171 | mDirtyRegion = region; |
| 172 | } |
| 173 | const Rect& Surface::swapRectangle() const { |
| 174 | return mSwapRectangle; |
| 175 | } |
| 176 | void Surface::setSwapRectangle(const Rect& r) { |
| 177 | mSwapRectangle = r; |
| 178 | } |
| 179 | |
| 180 | sp<Surface> Surface::readFromParcel(Parcel* parcel) |
| 181 | { |
| 182 | sp<SurfaceComposerClient> client; |
| 183 | ISurfaceFlingerClient::surface_data_t data; |
| 184 | sp<IBinder> clientBinder= parcel->readStrongBinder(); |
| 185 | sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder()); |
| 186 | data.heap[0] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); |
| 187 | data.heap[1] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); |
| 188 | data.token = parcel->readInt32(); |
| 189 | data.identity = parcel->readInt32(); |
| 190 | PixelFormat format = parcel->readInt32(); |
| 191 | uint32_t flags = parcel->readInt32(); |
| 192 | |
| 193 | if (clientBinder != NULL) |
| 194 | client = SurfaceComposerClient::clientForConnection(clientBinder); |
| 195 | |
| 196 | return new Surface(client, surface, data, 0, 0, format, flags, false); |
| 197 | } |
| 198 | |
| 199 | status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel) |
| 200 | { |
| 201 | uint32_t flags=0; |
| 202 | uint32_t format=0; |
| 203 | SurfaceID token = -1; |
| 204 | uint32_t identity = 0; |
| 205 | sp<SurfaceComposerClient> client; |
| 206 | sp<ISurface> sur; |
| 207 | sp<IMemoryHeap> heap[2]; |
| 208 | if (surface->isValid()) { |
| 209 | token = surface->mToken; |
| 210 | identity = surface->mIdentity; |
| 211 | client = surface->mClient; |
| 212 | sur = surface->mSurface; |
| 213 | heap[0] = surface->mHeap[0]; |
| 214 | heap[1] = surface->mHeap[1]; |
| 215 | format = surface->mFormat; |
| 216 | flags = surface->mFlags; |
| 217 | } |
| 218 | parcel->writeStrongBinder(client!=0 ? client->connection() : NULL); |
| 219 | parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); |
| 220 | parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); |
| 221 | parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); |
| 222 | parcel->writeInt32(token); |
| 223 | parcel->writeInt32(identity); |
| 224 | parcel->writeInt32(format); |
| 225 | parcel->writeInt32(flags); |
| 226 | return NO_ERROR; |
| 227 | } |
| 228 | |
| 229 | bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) |
| 230 | { |
| 231 | if (lhs == 0 || rhs == 0) |
| 232 | return false; |
| 233 | return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); |
| 234 | } |
| 235 | |
| 236 | void* Surface::heapBase(int i) const |
| 237 | { |
| 238 | void* heapBase = mSurfaceHeapBase[i]; |
| 239 | // map lazily so it doesn't get mapped in clients that don't need it |
| 240 | if (heapBase == 0) { |
| 241 | const sp<IMemoryHeap>& heap(mHeap[i]); |
| 242 | if (heap != 0) { |
| 243 | heapBase = static_cast<uint8_t*>(heap->base()); |
| 244 | if (heapBase == MAP_FAILED) { |
| 245 | heapBase = NULL; |
| 246 | LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)", |
| 247 | heap->asBinder().get(), heap.get()); |
| 248 | } |
| 249 | mSurfaceHeapBase[i] = heapBase; |
| 250 | } |
| 251 | } |
| 252 | return heapBase; |
| 253 | } |
| 254 | |
| 255 | }; // namespace android |
| 256 | |