Layer.cpp revision 81b0aa696ac954180caec6cb8cc1bb97440e03b5
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#include <stdlib.h>
18#include <stdint.h>
19#include <sys/types.h>
20
21#include <cutils/properties.h>
22#include <cutils/native_handle.h>
23
24#include <utils/Errors.h>
25#include <utils/Log.h>
26#include <utils/StopWatch.h>
27#include <utils/IMemory.h>
28
29#include <ui/PixelFormat.h>
30#include <ui/Surface.h>
31
32#include "clz.h"
33#include "Layer.h"
34#include "LayerBitmap.h"
35#include "SurfaceFlinger.h"
36#include "DisplayHardware/DisplayHardware.h"
37
38
39#define DEBUG_RESIZE    0
40
41
42namespace android {
43
44// ---------------------------------------------------------------------------
45
46const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
47const char* const Layer::typeID = "Layer";
48
49// ---------------------------------------------------------------------------
50
51Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
52    :   LayerBaseClient(flinger, display, c, i),
53        mSecure(false),
54        mFrontBufferIndex(1),
55        mNeedsBlending(true),
56        mResizeTransactionDone(false)
57{
58    // no OpenGL operation is possible here, since we might not be
59    // in the OpenGL thread.
60}
61
62Layer::~Layer()
63{
64    destroy();
65    // the actual buffers will be destroyed here
66}
67
68void Layer::destroy()
69{
70    for (int i=0 ; i<NUM_BUFFERS ; i++) {
71        if (mTextures[i].name != -1U) {
72            // FIXME: this was originally to work-around a bug in the
73            // adreno driver. this should be fixed now.
74            glDeleteTextures(1, &mTextures[i].name);
75            mTextures[i].name = -1U;
76        }
77        if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
78            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
79            eglDestroyImageKHR(dpy, mTextures[i].image);
80            mTextures[i].image = EGL_NO_IMAGE_KHR;
81        }
82    }
83}
84
85void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
86{
87    LayerBase::initStates(w,h,flags);
88
89    if (flags & ISurfaceComposer::eDestroyBackbuffer)
90        lcblk->flags |= eNoCopyBack;
91}
92
93sp<LayerBaseClient::Surface> Layer::createSurface() const
94{
95    return mSurface;
96}
97
98status_t Layer::ditch()
99{
100    // the layer is not on screen anymore. free as much resources as possible
101    mSurface.clear();
102    destroy();
103    return NO_ERROR;
104}
105
106status_t Layer::setBuffers( Client* client,
107                            uint32_t w, uint32_t h,
108                            PixelFormat format, uint32_t flags)
109{
110    PixelFormatInfo info;
111    status_t err = getPixelFormatInfo(format, &info);
112    if (err) return err;
113
114    uint32_t bufferFlags = 0;
115    if (flags & ISurfaceComposer::eGPU)
116        bufferFlags |= Buffer::GPU;
117
118    if (flags & ISurfaceComposer::eSecure)
119        bufferFlags |= Buffer::SECURE;
120
121
122    if (bufferFlags & Buffer::GPU) {
123        // FIXME: this is msm7201A specific, as its GPU only supports
124        // BGRA_8888.
125        if (format == PIXEL_FORMAT_RGBA_8888) {
126            format = PIXEL_FORMAT_BGRA_8888;
127        }
128    }
129
130    mSecure = (bufferFlags & Buffer::SECURE) ? true : false;
131    mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
132    for (int i=0 ; i<2 ; i++) {
133        err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags);
134        if (err != NO_ERROR) {
135            return err;
136        }
137    }
138    mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
139    return NO_ERROR;
140}
141
142void Layer::reloadTexture(const Region& dirty)
143{
144    const sp<const Buffer>& buffer(frontBuffer().getBuffer());
145     if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
146        int index = mFrontBufferIndex;
147        if (LIKELY(!mTextures[index].dirty)) {
148            glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
149        } else {
150            // we need to recreate the texture
151            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
152
153            // create the new texture name if needed
154            if (UNLIKELY(mTextures[index].name == -1U)) {
155                mTextures[index].name = createTexture();
156            } else {
157                glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
158            }
159
160            // free the previous image
161            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
162                eglDestroyImageKHR(dpy, mTextures[index].image);
163                mTextures[index].image = EGL_NO_IMAGE_KHR;
164            }
165
166            // construct an EGL_NATIVE_BUFFER_ANDROID
167            android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
168
169            // create the new EGLImageKHR
170            const EGLint attrs[] = {
171                    EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
172                    EGL_NONE,                   EGL_NONE
173            };
174            mTextures[index].image = eglCreateImageKHR(
175                    dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
176                    (EGLClientBuffer)clientBuf, attrs);
177
178            LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR,
179                    "eglCreateImageKHR() failed. err=0x%4x",
180                    eglGetError());
181
182            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
183                glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
184                        (GLeglImageOES)mTextures[index].image);
185                GLint error = glGetError();
186                if (UNLIKELY(error != GL_NO_ERROR)) {
187                    // this failed, for instance, because we don't support
188                    // NPOT.
189                    // FIXME: do something!
190                    mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
191                } else {
192                    // Everything went okay!
193                    mTextures[index].dirty = false;
194                }
195            }
196        }
197    } else {
198        GGLSurface t;
199        if (LIKELY(buffer->getBitmapSurface(&t) == NO_ERROR)) {
200            if (UNLIKELY(mTextures[0].name == -1U)) {
201                mTextures[0].name = createTexture();
202            }
203            loadTexture(dirty, mTextures[0].name, t,
204                    mTextures[0].width, mTextures[0].height);
205        }
206    }
207}
208
209
210void Layer::onDraw(const Region& clip) const
211{
212    const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ?
213            mFrontBufferIndex : 0;
214    GLuint textureName = mTextures[index].name;
215
216    if (UNLIKELY(textureName == -1LU)) {
217        LOGW("Layer %p doesn't have a texture", this);
218        // the texture has not been created yet, this Layer has
219        // in fact never been drawn into. this happens frequently with
220        // SurfaceView.
221        clearWithOpenGL(clip);
222        return;
223    }
224
225    GGLSurface t;
226    sp<const Buffer> buffer(frontBuffer().getBuffer());
227    buffer->getBitmapSurface(&t);
228    drawWithOpenGL(clip, textureName, t);
229}
230
231sp<SurfaceBuffer> Layer::peekBuffer()
232{
233    /*
234     * This is called from the client's Surface::lock(), after it locked
235     * the surface successfully. We're therefore guaranteed that the
236     * back-buffer is not in use by ourselves.
237     * Of course, we need to validate all this, which is not trivial.
238     *
239     * FIXME: A resize could happen at any time here. What to do about this?
240     *  - resize() form post()
241     *  - resize() from doTransaction()
242     *
243     *  We'll probably need an internal lock for this.
244     *
245     *
246     * TODO: We need to make sure that post() doesn't swap
247     *       the buffers under us.
248     */
249
250    // it's okay to read swapState for the purpose of figuring out the
251    // backbuffer index, which cannot change (since the app has locked it).
252    const uint32_t state = lcblk->swapState;
253    const int32_t backBufferIndex = layer_cblk_t::backBuffer(state);
254
255    // get rid of the EGL image, since we shouldn't need it anymore
256    // (note that we're in a different thread than where it is being used)
257    if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) {
258        EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
259        eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image);
260        mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR;
261    }
262
263    LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
264    sp<SurfaceBuffer> buffer = layerBitmap.allocate();
265
266    LOGD_IF(DEBUG_RESIZE,
267            "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
268            this, backBufferIndex,
269            layerBitmap.getWidth(),
270            layerBitmap.getHeight(),
271            layerBitmap.getBuffer()->getWidth(),
272            layerBitmap.getBuffer()->getHeight());
273
274    if (UNLIKELY(buffer == 0)) {
275        // XXX: what to do, what to do?
276    } else {
277        // texture is now dirty...
278        mTextures[backBufferIndex].dirty = true;
279        // ... so it the visible region (because we consider the surface's
280        // buffer size for visibility calculations)
281        forceVisibilityTransaction();
282        mFlinger->setTransactionFlags(eTraversalNeeded);
283    }
284    return buffer;
285}
286
287uint32_t Layer::doTransaction(uint32_t flags)
288{
289    const Layer::State& front(drawingState());
290    const Layer::State& temp(currentState());
291
292    // the test front.{w|h} != temp.{w|h} is not enough because it is possible
293    // that the size changed back to its previous value before the buffer
294    // was resized (in the eLocked case below), in which case, we still
295    // need to execute the code below so the clients have a chance to be
296    // release. resize() deals with the fact that the size can be the same.
297
298    /*
299     *  Various states we could be in...
300
301         resize = state & eResizeRequested;
302         if (backbufferChanged) {
303             if (resize == 0) {
304                 // ERROR, the resized buffer doesn't have its resize flag set
305             } else if (resize == mask) {
306                 // ERROR one of the buffer has already been resized
307             } else if (resize == mask ^ eResizeRequested) {
308                 // ERROR, the resized buffer doesn't have its resize flag set
309             } else if (resize == eResizeRequested) {
310                 // OK, Normal case, proceed with resize
311             }
312         } else {
313             if (resize == 0) {
314                 // OK, nothing special, do nothing
315             } else if (resize == mask) {
316                 // restarted transaction, do nothing
317             } else if (resize == mask ^ eResizeRequested) {
318                 // restarted transaction, do nothing
319             } else if (resize == eResizeRequested) {
320                 // OK, size reset to previous value, proceed with resize
321             }
322         }
323     */
324
325    // Index of the back buffer
326    const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
327    const uint32_t state = lcblk->swapState;
328    const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
329    const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
330    uint32_t resizeFlags = state & eResizeRequested;
331
332    if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
333        LOGE(   "backbuffer size changed, but both resize flags are not set! "
334                "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
335                "index=%d, (%dx%d), (%dx%d)",
336                this,  state,
337                int(temp.w), int(temp.h),
338                int(drawingState().w), int(drawingState().h),
339                int(clientBackBufferIndex),
340                int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
341                int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
342        // if we get there we're pretty screwed. the only reasonable
343        // thing to do is to pretend we should do the resize since
344        // backbufferChanged is set (this also will give a chance to
345        // client to get unblocked)
346        resizeFlags = eResizeRequested;
347    }
348
349    if (resizeFlags == eResizeRequested)  {
350        // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
351        // here, would be wrong and misleading because by this point
352        // mFrontBufferIndex has not been updated yet.
353
354        LOGD_IF(DEBUG_RESIZE,
355                    "resize (layer=%p), state=%08x, "
356                    "requested (%dx%d), "
357                    "drawing (%d,%d), "
358                    "index=%d, (%dx%d), (%dx%d)",
359                    this,  state,
360                    int(temp.w), int(temp.h),
361                    int(drawingState().w), int(drawingState().h),
362                    int(clientBackBufferIndex),
363                    int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
364                    int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
365
366        if (state & eLocked) {
367            // if the buffer is locked, we can't resize anything because
368            // - the backbuffer is currently in use by the user
369            // - the front buffer is being shown
370            // We just act as if the transaction didn't happen and we
371            // reschedule it later...
372            flags |= eRestartTransaction;
373        } else {
374            // This buffer needs to be resized
375            status_t err =
376                resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
377            if (err == NO_ERROR) {
378                const uint32_t mask = clientBackBufferIndex ?
379                        eResizeBuffer1 : eResizeBuffer0;
380                android_atomic_and(~mask, &(lcblk->swapState));
381                // since a buffer became available, we can let the client go...
382                mFlinger->scheduleBroadcast(client);
383                mResizeTransactionDone = true;
384
385                // we're being resized and there is a freeze display request,
386                // acquire a freeze lock, so that the screen stays put
387                // until we've redrawn at the new size; this is to avoid
388                // glitches upon orientation changes.
389                if (mFlinger->hasFreezeRequest()) {
390                    // if the surface is hidden, don't try to acquire the
391                    // freeze lock, since hidden surfaces may never redraw
392                    if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
393                        mFreezeLock = mFlinger->getFreezeLock();
394                    }
395                }
396            }
397        }
398    }
399
400    if (temp.sequence != front.sequence) {
401        if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
402            // this surface is now hidden, so it shouldn't hold a freeze lock
403            // (it may never redraw, which is fine if it is hidden)
404            mFreezeLock.clear();
405        }
406    }
407
408    return LayerBase::doTransaction(flags);
409}
410
411status_t Layer::resize(
412        int32_t clientBackBufferIndex,
413        uint32_t width, uint32_t height,
414        const char* what)
415{
416    /*
417     * handle resize (backbuffer and frontbuffer reallocation)
418     * this is called from post() or from doTransaction()
419     */
420
421    const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
422
423    // if the new (transaction) size is != from the the backbuffer
424    // then we need to reallocate the backbuffer
425    bool backbufferChanged = (clientBackBuffer.getWidth()  != width) ||
426                             (clientBackBuffer.getHeight() != height);
427
428    LOGD_IF(!backbufferChanged,
429            "(%s) eResizeRequested (layer=%p), but size not changed: "
430            "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
431            "state=%08lx, index=%d, (%dx%d), (%dx%d)",
432            what, this,
433            int(width), int(height),
434            int(drawingState().w), int(drawingState().h),
435            int(currentState().w), int(currentState().h),
436            long(lcblk->swapState),
437            int(clientBackBufferIndex),
438            int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
439            int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
440
441    // this can happen when changing the size back and forth quickly
442    status_t err = NO_ERROR;
443    if (backbufferChanged) {
444
445        LOGD_IF(DEBUG_RESIZE,
446                "resize (layer=%p), requested (%dx%d), "
447                "index=%d, (%dx%d), (%dx%d)",
448                this, int(width), int(height), int(clientBackBufferIndex),
449                int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
450                int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
451
452        err = mBuffers[clientBackBufferIndex].setSize(width, height);
453        if (UNLIKELY(err != NO_ERROR)) {
454            // This really should never happen
455            LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
456                    clientBackBufferIndex, width, height, err, strerror(err));
457            // couldn't reallocate the surface
458            android_atomic_write(eInvalidSurface, &lcblk->swapState);
459        }
460    }
461    return err;
462}
463
464void Layer::setSizeChanged(uint32_t w, uint32_t h)
465{
466    LOGD_IF(DEBUG_RESIZE,
467            "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
468            w, h, mCurrentState.w, mCurrentState.h);
469    android_atomic_or(eResizeRequested, &(lcblk->swapState));
470}
471
472// ----------------------------------------------------------------------------
473// pageflip handling...
474// ----------------------------------------------------------------------------
475
476void Layer::lockPageFlip(bool& recomputeVisibleRegions)
477{
478    uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
479    // preemptively block the client, because he might set
480    // eFlipRequested at any time and want to use this buffer
481    // for the next frame. This will be unset below if it
482    // turns out we didn't need it.
483
484    uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
485    if (!(state & mask))
486        return;
487
488    if (UNLIKELY(state & eInvalidSurface)) {
489        // if eInvalidSurface is set, this means the surface
490        // became invalid during a transaction (NO_MEMORY for instance)
491        mFlinger->scheduleBroadcast(client);
492        return;
493    }
494
495    if (UNLIKELY(state & eFlipRequested)) {
496        uint32_t oldState;
497        mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
498        if (oldState & eNextFlipPending) {
499            // Process another round (we know at least a buffer
500            // is ready for that client).
501            mFlinger->signalEvent();
502        }
503    }
504}
505
506Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
507{
508    // atomically swap buffers and (re)set eFlipRequested
509    int32_t oldValue, newValue;
510    layer_cblk_t * const lcblk = this->lcblk;
511    do {
512        oldValue = lcblk->swapState;
513            // get the current value
514
515        LOG_ASSERT(oldValue&eFlipRequested,
516            "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
517            long(oldValue));
518
519        newValue = (oldValue ^ eIndex);
520            // swap buffers
521
522        newValue &= ~(eFlipRequested | eNextFlipPending);
523            // clear eFlipRequested and eNextFlipPending
524
525        if (oldValue & eNextFlipPending)
526            newValue |= eFlipRequested;
527            // if eNextFlipPending is set (second buffer already has something
528            // in it) we need to reset eFlipRequested because the client
529            // might never do it
530
531    } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
532    *previousSate = oldValue;
533
534    const int32_t index = (newValue & eIndex) ^ 1;
535    mFrontBufferIndex = index;
536
537    /* NOTE: it's safe to set this flag here because this is only touched
538     * from LayerBitmap::allocate(), which by construction cannot happen
539     * while we're in post().
540     */
541    lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty;
542
543    // ... post the new front-buffer
544    Region dirty(lcblk->region + index);
545    dirty.andSelf(frontBuffer().getBounds());
546
547    //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
548    //    oldValue, newValue, mFrontBufferIndex);
549    //dirty.dump("dirty");
550
551    if (UNLIKELY(oldValue & eResizeRequested)) {
552
553        LOGD_IF(DEBUG_RESIZE,
554                     "post (layer=%p), state=%08x, "
555                     "index=%d, (%dx%d), (%dx%d)",
556                     this,  newValue,
557                     int(1-index),
558                     int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
559                     int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
560
561        // here, we just posted the surface and we have resolved
562        // the front/back buffer indices. The client is blocked, so
563        // it cannot start using the new backbuffer.
564
565        // If the backbuffer was resized in THIS round, we actually cannot
566        // resize the frontbuffer because it has *just* been drawn (and we
567        // would have nothing to draw). In this case we just skip the resize
568        // it'll happen after the next page flip or during the next
569        // transaction.
570
571        const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
572        if (mResizeTransactionDone && (newValue & mask)) {
573            // Resize the layer's second buffer only if the transaction
574            // happened. It may not have happened yet if eResizeRequested
575            // was set immediately after the "transactionRequested" test,
576            // in which case the drawing state's size would be wrong.
577            mFreezeLock.clear();
578            const Layer::State& s(drawingState());
579            if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
580                do {
581                    oldValue = lcblk->swapState;
582                    if ((oldValue & eResizeRequested) == eResizeRequested) {
583                        // ugh, another resize was requested since we processed
584                        // the first buffer, don't free the client, and let
585                        // the next transaction handle everything.
586                        break;
587                    }
588                    newValue = oldValue & ~mask;
589                } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
590            }
591            mResizeTransactionDone = false;
592            recomputeVisibleRegions = true;
593            this->contentDirty = true;
594        }
595    }
596
597    reloadTexture(dirty);
598
599    return dirty;
600}
601
602Point Layer::getPhysicalSize() const
603{
604    sp<const Buffer> front(frontBuffer().getBuffer());
605    return Point(front->getWidth(), front->getHeight());
606}
607
608void Layer::unlockPageFlip(
609        const Transform& planeTransform, Region& outDirtyRegion)
610{
611    Region dirtyRegion(mPostedDirtyRegion);
612    if (!dirtyRegion.isEmpty()) {
613        mPostedDirtyRegion.clear();
614        // The dirty region is given in the layer's coordinate space
615        // transform the dirty region by the surface's transformation
616        // and the global transformation.
617        const Layer::State& s(drawingState());
618        const Transform tr(planeTransform * s.transform);
619        dirtyRegion = tr.transform(dirtyRegion);
620
621        // At this point, the dirty region is in screen space.
622        // Make sure it's constrained by the visible region (which
623        // is in screen space as well).
624        dirtyRegion.andSelf(visibleRegionScreen);
625        outDirtyRegion.orSelf(dirtyRegion);
626
627        // client could be blocked, so signal them so they get a
628        // chance to reevaluate their condition.
629        mFlinger->scheduleBroadcast(client);
630    }
631}
632
633void Layer::finishPageFlip()
634{
635    if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
636        LOGE_IF(!(lcblk->swapState & eBusy),
637                "layer %p wasn't locked!", this);
638        android_atomic_and(~eBusy, &(lcblk->swapState));
639    }
640    mFlinger->scheduleBroadcast(client);
641}
642
643// ---------------------------------------------------------------------------
644
645Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
646        SurfaceID id, const sp<Layer>& owner)
647    : Surface(flinger, id, owner->getIdentity(), owner)
648{
649}
650
651Layer::SurfaceLayer::~SurfaceLayer()
652{
653}
654
655sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
656{
657    sp<SurfaceBuffer> buffer = 0;
658    sp<Layer> owner(getOwner());
659    if (owner != 0) {
660        buffer = owner->peekBuffer();
661    }
662    return buffer;
663}
664
665// ---------------------------------------------------------------------------
666
667
668}; // namespace android
669