Surface.cpp revision bd050ab2af1421d527d1a80ce59dd8d9940a838c
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
42namespace android {
43
44// ============================================================================
45//  SurfaceControl
46// ============================================================================
47
48SurfaceControl::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
57SurfaceControl::~SurfaceControl()
58{
59    destroy();
60}
61
62void 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
75void 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
86bool 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
94status_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}
100status_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}
106status_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}
112status_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}
118status_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}
124status_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}
130status_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}
136status_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}
142status_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}
148status_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}
154status_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}
160status_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
167status_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
177status_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
192sp<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
208Surface::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
220Surface::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
236Surface::Surface(const sp<ISurfaceTexture>& st)
237    : SurfaceTextureClient(),
238      mSurface(NULL),
239      mIdentity(0)
240{
241    init(st);
242}
243
244status_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
270Mutex Surface::sCachedSurfacesLock;
271DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
272
273sp<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    }
281    if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) {
282        surface = 0;
283    }
284    cleanCachedSurfacesLocked();
285    return surface;
286}
287
288// Remove the stale entries from the surface cache.  This should only be called
289// with sCachedSurfacesLock held.
290void Surface::cleanCachedSurfacesLocked() {
291    for (int i = sCachedSurfaces.size()-1; i >= 0; --i) {
292        wp<Surface> s(sCachedSurfaces.valueAt(i));
293        if (s == 0 || s.promote() == 0) {
294            sCachedSurfaces.removeItemsAt(i);
295        }
296    }
297}
298
299void Surface::init(const sp<ISurfaceTexture>& surfaceTexture)
300{
301    if (mSurface != NULL || surfaceTexture != NULL) {
302        LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
303        if (surfaceTexture != NULL) {
304            setISurfaceTexture(surfaceTexture);
305            setUsage(GraphicBuffer::USAGE_HW_RENDER);
306        }
307
308        DisplayInfo dinfo;
309        SurfaceComposerClient::getDisplayInfo(0, &dinfo);
310        const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
311        const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
312        const_cast<uint32_t&>(ANativeWindow::flags) = 0;
313    }
314}
315
316Surface::~Surface()
317{
318    // clear all references and trigger an IPC now, to make sure things
319    // happen without delay, since these resources are quite heavy.
320    mSurface.clear();
321    IPCThreadState::self()->flushCommands();
322}
323
324bool Surface::isValid() {
325    return getISurfaceTexture() != NULL;
326}
327
328sp<ISurfaceTexture> Surface::getSurfaceTexture() {
329    return getISurfaceTexture();
330}
331
332sp<IBinder> Surface::asBinder() const {
333    return mSurface!=0 ? mSurface->asBinder() : 0;
334}
335
336// ----------------------------------------------------------------------------
337
338int Surface::query(int what, int* value) const {
339    switch (what) {
340    case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
341        *value = 1;
342        return NO_ERROR;
343    case NATIVE_WINDOW_CONCRETE_TYPE:
344        *value = NATIVE_WINDOW_SURFACE;
345        return NO_ERROR;
346    }
347    return SurfaceTextureClient::query(what, value);
348}
349
350// ----------------------------------------------------------------------------
351
352status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn) {
353    ANativeWindow_Buffer outBuffer;
354
355    ARect temp;
356    ARect* inOutDirtyBounds = NULL;
357    if (dirtyIn) {
358        temp = dirtyIn->getBounds();
359        inOutDirtyBounds = &temp;
360    }
361
362    status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds);
363
364    if (err == NO_ERROR) {
365        other->w = uint32_t(outBuffer.width);
366        other->h = uint32_t(outBuffer.height);
367        other->s = uint32_t(outBuffer.stride);
368        other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
369        other->format = uint32_t(outBuffer.format);
370        other->bits = outBuffer.bits;
371    }
372    return err;
373}
374
375status_t Surface::unlockAndPost() {
376    return SurfaceTextureClient::unlockAndPost();
377}
378
379// ----------------------------------------------------------------------------
380}; // namespace android
381