Layer.cpp revision 1681d95989271f3a9ac0dbb93d10e4a29f2b4444
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 ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
22#include <math.h>
23
24#include <cutils/compiler.h>
25#include <cutils/native_handle.h>
26#include <cutils/properties.h>
27
28#include <utils/Errors.h>
29#include <utils/Log.h>
30#include <utils/NativeHandle.h>
31#include <utils/StopWatch.h>
32#include <utils/Trace.h>
33
34#include <ui/GraphicBuffer.h>
35#include <ui/PixelFormat.h>
36
37#include <gui/Surface.h>
38
39#include "clz.h"
40#include "Colorizer.h"
41#include "DisplayDevice.h"
42#include "Layer.h"
43#include "MonitoredProducer.h"
44#include "SurfaceFlinger.h"
45
46#include "DisplayHardware/HWComposer.h"
47
48#include "RenderEngine/RenderEngine.h"
49
50#define DEBUG_RESIZE    0
51
52namespace android {
53
54// ---------------------------------------------------------------------------
55
56int32_t Layer::sSequence = 1;
57
58Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
59        const String8& name, uint32_t w, uint32_t h, uint32_t flags)
60    :   contentDirty(false),
61        sequence(uint32_t(android_atomic_inc(&sSequence))),
62        mFlinger(flinger),
63        mTextureName(-1U),
64        mPremultipliedAlpha(true),
65        mName("unnamed"),
66        mDebug(false),
67        mFormat(PIXEL_FORMAT_NONE),
68        mTransactionFlags(0),
69        mQueuedFrames(0),
70        mSidebandStreamChanged(false),
71        mCurrentTransform(0),
72        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
73        mCurrentOpacity(true),
74        mRefreshPending(false),
75        mFrameLatencyNeeded(false),
76        mFiltering(false),
77        mNeedsFiltering(false),
78        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
79        mSecure(false),
80        mProtectedByApp(false),
81        mHasSurface(false),
82        mClientRef(client)
83{
84    mCurrentCrop.makeInvalid();
85    mFlinger->getRenderEngine().genTextures(1, &mTextureName);
86    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
87
88    uint32_t layerFlags = 0;
89    if (flags & ISurfaceComposerClient::eHidden)
90        layerFlags |= layer_state_t::eLayerHidden;
91    if (flags & ISurfaceComposerClient::eOpaque)
92        layerFlags |= layer_state_t::eLayerOpaque;
93
94    if (flags & ISurfaceComposerClient::eNonPremultiplied)
95        mPremultipliedAlpha = false;
96
97    mName = name;
98
99    mCurrentState.active.w = w;
100    mCurrentState.active.h = h;
101    mCurrentState.active.crop.makeInvalid();
102    mCurrentState.z = 0;
103    mCurrentState.alpha = 0xFF;
104    mCurrentState.layerStack = 0;
105    mCurrentState.flags = layerFlags;
106    mCurrentState.sequence = 0;
107    mCurrentState.transform.set(0, 0);
108    mCurrentState.requested = mCurrentState.active;
109
110    // drawing state & current state are identical
111    mDrawingState = mCurrentState;
112
113    nsecs_t displayPeriod =
114            flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
115    mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
116}
117
118void Layer::onFirstRef() {
119    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
120    sp<IGraphicBufferProducer> producer;
121    sp<IGraphicBufferConsumer> consumer;
122    BufferQueue::createBufferQueue(&producer, &consumer);
123    mProducer = new MonitoredProducer(producer, mFlinger);
124    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
125    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
126    mSurfaceFlingerConsumer->setContentsChangedListener(this);
127    mSurfaceFlingerConsumer->setName(mName);
128
129#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
130#warning "disabling triple buffering"
131    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
132#else
133    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
134#endif
135
136    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
137    updateTransformHint(hw);
138}
139
140Layer::~Layer() {
141    sp<Client> c(mClientRef.promote());
142    if (c != 0) {
143        c->detachLayer(this);
144    }
145    mFlinger->deleteTextureAsync(mTextureName);
146    mFrameTracker.logAndResetStats(mName);
147}
148
149// ---------------------------------------------------------------------------
150// callbacks
151// ---------------------------------------------------------------------------
152
153void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
154        HWComposer::HWCLayerInterface* layer) {
155    if (layer) {
156        layer->onDisplayed();
157        mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
158    }
159}
160
161void Layer::onFrameAvailable() {
162    android_atomic_inc(&mQueuedFrames);
163    mFlinger->signalLayerUpdate();
164}
165
166void Layer::onSidebandStreamChanged() {
167    if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
168        // mSidebandStreamChanged was false
169        mFlinger->signalLayerUpdate();
170    }
171}
172
173// called with SurfaceFlinger::mStateLock from the drawing thread after
174// the layer has been remove from the current state list (and just before
175// it's removed from the drawing state list)
176void Layer::onRemoved() {
177    mSurfaceFlingerConsumer->abandon();
178}
179
180// ---------------------------------------------------------------------------
181// set-up
182// ---------------------------------------------------------------------------
183
184const String8& Layer::getName() const {
185    return mName;
186}
187
188status_t Layer::setBuffers( uint32_t w, uint32_t h,
189                            PixelFormat format, uint32_t flags)
190{
191    uint32_t const maxSurfaceDims = min(
192            mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
193
194    // never allow a surface larger than what our underlying GL implementation
195    // can handle.
196    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
197        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
198        return BAD_VALUE;
199    }
200
201    mFormat = format;
202
203    mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
204    mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
205    mCurrentOpacity = getOpacityForFormat(format);
206
207    mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
208    mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
209    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
210
211    return NO_ERROR;
212}
213
214sp<IBinder> Layer::getHandle() {
215    Mutex::Autolock _l(mLock);
216
217    LOG_ALWAYS_FATAL_IF(mHasSurface,
218            "Layer::getHandle() has already been called");
219
220    mHasSurface = true;
221
222    /*
223     * The layer handle is just a BBinder object passed to the client
224     * (remote process) -- we don't keep any reference on our side such that
225     * the dtor is called when the remote side let go of its reference.
226     *
227     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
228     * this layer when the handle is destroyed.
229     */
230
231    class Handle : public BBinder, public LayerCleaner {
232        wp<const Layer> mOwner;
233    public:
234        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
235            : LayerCleaner(flinger, layer), mOwner(layer) {
236        }
237    };
238
239    return new Handle(mFlinger, this);
240}
241
242sp<IGraphicBufferProducer> Layer::getProducer() const {
243    return mProducer;
244}
245
246// ---------------------------------------------------------------------------
247// h/w composer set-up
248// ---------------------------------------------------------------------------
249
250Rect Layer::getContentCrop() const {
251    // this is the crop rectangle that applies to the buffer
252    // itself (as opposed to the window)
253    Rect crop;
254    if (!mCurrentCrop.isEmpty()) {
255        // if the buffer crop is defined, we use that
256        crop = mCurrentCrop;
257    } else if (mActiveBuffer != NULL) {
258        // otherwise we use the whole buffer
259        crop = mActiveBuffer->getBounds();
260    } else {
261        // if we don't have a buffer yet, we use an empty/invalid crop
262        crop.makeInvalid();
263    }
264    return crop;
265}
266
267static Rect reduce(const Rect& win, const Region& exclude) {
268    if (CC_LIKELY(exclude.isEmpty())) {
269        return win;
270    }
271    if (exclude.isRect()) {
272        return win.reduce(exclude.getBounds());
273    }
274    return Region(win).subtract(exclude).getBounds();
275}
276
277Rect Layer::computeBounds() const {
278    const Layer::State& s(getDrawingState());
279    Rect win(s.active.w, s.active.h);
280    if (!s.active.crop.isEmpty()) {
281        win.intersect(s.active.crop, &win);
282    }
283    // subtract the transparent region and snap to the bounds
284    return reduce(win, s.activeTransparentRegion);
285}
286
287FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
288    // the content crop is the area of the content that gets scaled to the
289    // layer's size.
290    FloatRect crop(getContentCrop());
291
292    // the active.crop is the area of the window that gets cropped, but not
293    // scaled in any ways.
294    const State& s(getDrawingState());
295
296    // apply the projection's clipping to the window crop in
297    // layerstack space, and convert-back to layer space.
298    // if there are no window scaling involved, this operation will map to full
299    // pixels in the buffer.
300    // FIXME: the 3 lines below can produce slightly incorrect clipping when we have
301    // a viewport clipping and a window transform. we should use floating point to fix this.
302
303    Rect activeCrop(s.active.w, s.active.h);
304    if (!s.active.crop.isEmpty()) {
305        activeCrop = s.active.crop;
306    }
307
308    activeCrop = s.transform.transform(activeCrop);
309    activeCrop.intersect(hw->getViewport(), &activeCrop);
310    activeCrop = s.transform.inverse().transform(activeCrop);
311
312    // paranoia: make sure the window-crop is constrained in the
313    // window's bounds
314    activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
315
316    // subtract the transparent region and snap to the bounds
317    activeCrop = reduce(activeCrop, s.activeTransparentRegion);
318
319    if (!activeCrop.isEmpty()) {
320        // Transform the window crop to match the buffer coordinate system,
321        // which means using the inverse of the current transform set on the
322        // SurfaceFlingerConsumer.
323        uint32_t invTransform = mCurrentTransform;
324        int winWidth = s.active.w;
325        int winHeight = s.active.h;
326        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
327            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
328                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
329            winWidth = s.active.h;
330            winHeight = s.active.w;
331        }
332        const Rect winCrop = activeCrop.transform(
333                invTransform, s.active.w, s.active.h);
334
335        // below, crop is intersected with winCrop expressed in crop's coordinate space
336        float xScale = crop.getWidth()  / float(winWidth);
337        float yScale = crop.getHeight() / float(winHeight);
338
339        float insetL = winCrop.left                 * xScale;
340        float insetT = winCrop.top                  * yScale;
341        float insetR = (winWidth  - winCrop.right ) * xScale;
342        float insetB = (winHeight - winCrop.bottom) * yScale;
343
344        crop.left   += insetL;
345        crop.top    += insetT;
346        crop.right  -= insetR;
347        crop.bottom -= insetB;
348    }
349    return crop;
350}
351
352void Layer::setGeometry(
353    const sp<const DisplayDevice>& hw,
354        HWComposer::HWCLayerInterface& layer)
355{
356    layer.setDefaultState();
357
358    // enable this layer
359    layer.setSkip(false);
360
361    if (isSecure() && !hw->isSecure()) {
362        layer.setSkip(true);
363    }
364
365    // this gives us only the "orientation" component of the transform
366    const State& s(getDrawingState());
367    if (!isOpaque(s) || s.alpha != 0xFF) {
368        layer.setBlending(mPremultipliedAlpha ?
369                HWC_BLENDING_PREMULT :
370                HWC_BLENDING_COVERAGE);
371    }
372
373    // apply the layer's transform, followed by the display's global transform
374    // here we're guaranteed that the layer's transform preserves rects
375    Rect frame(s.transform.transform(computeBounds()));
376    frame.intersect(hw->getViewport(), &frame);
377    const Transform& tr(hw->getTransform());
378    layer.setFrame(tr.transform(frame));
379    layer.setCrop(computeCrop(hw));
380    layer.setPlaneAlpha(s.alpha);
381
382    /*
383     * Transformations are applied in this order:
384     * 1) buffer orientation/flip/mirror
385     * 2) state transformation (window manager)
386     * 3) layer orientation (screen orientation)
387     * (NOTE: the matrices are multiplied in reverse order)
388     */
389
390    const Transform bufferOrientation(mCurrentTransform);
391    Transform transform(tr * s.transform * bufferOrientation);
392
393    if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
394        /*
395         * the code below applies the display's inverse transform to the buffer
396         */
397        uint32_t invTransform = hw->getOrientationTransform();
398        // calculate the inverse transform
399        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
400            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
401                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
402        }
403        // and apply to the current transform
404        transform = transform * Transform(invTransform);
405    }
406
407    // this gives us only the "orientation" component of the transform
408    const uint32_t orientation = transform.getOrientation();
409    if (orientation & Transform::ROT_INVALID) {
410        // we can only handle simple transformation
411        layer.setSkip(true);
412    } else {
413        layer.setTransform(orientation);
414    }
415}
416
417void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
418        HWComposer::HWCLayerInterface& layer) {
419    // we have to set the visible region on every frame because
420    // we currently free it during onLayerDisplayed(), which is called
421    // after HWComposer::commit() -- every frame.
422    // Apply this display's projection's viewport to the visible region
423    // before giving it to the HWC HAL.
424    const Transform& tr = hw->getTransform();
425    Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
426    layer.setVisibleRegionScreen(visible);
427
428    if (mSidebandStream.get()) {
429        layer.setSidebandStream(mSidebandStream);
430    } else {
431        // NOTE: buffer can be NULL if the client never drew into this
432        // layer yet, or if we ran out of memory
433        layer.setBuffer(mActiveBuffer);
434    }
435}
436
437void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
438        HWComposer::HWCLayerInterface& layer) {
439    int fenceFd = -1;
440
441    // TODO: there is a possible optimization here: we only need to set the
442    // acquire fence the first time a new buffer is acquired on EACH display.
443
444    if (layer.getCompositionType() == HWC_OVERLAY) {
445        sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
446        if (fence->isValid()) {
447            fenceFd = fence->dup();
448            if (fenceFd == -1) {
449                ALOGW("failed to dup layer fence, skipping sync: %d", errno);
450            }
451        }
452    }
453    layer.setAcquireFenceFd(fenceFd);
454}
455
456// ---------------------------------------------------------------------------
457// drawing...
458// ---------------------------------------------------------------------------
459
460void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
461    onDraw(hw, clip, false);
462}
463
464void Layer::draw(const sp<const DisplayDevice>& hw,
465        bool useIdentityTransform) const {
466    onDraw(hw, Region(hw->bounds()), useIdentityTransform);
467}
468
469void Layer::draw(const sp<const DisplayDevice>& hw) const {
470    onDraw(hw, Region(hw->bounds()), false);
471}
472
473void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
474        bool useIdentityTransform) const
475{
476    ATRACE_CALL();
477
478    if (CC_UNLIKELY(mActiveBuffer == 0)) {
479        // the texture has not been created yet, this Layer has
480        // in fact never been drawn into. This happens frequently with
481        // SurfaceView because the WindowManager can't know when the client
482        // has drawn the first time.
483
484        // If there is nothing under us, we paint the screen in black, otherwise
485        // we just skip this update.
486
487        // figure out if there is something below us
488        Region under;
489        const SurfaceFlinger::LayerVector& drawingLayers(
490                mFlinger->mDrawingState.layersSortedByZ);
491        const size_t count = drawingLayers.size();
492        for (size_t i=0 ; i<count ; ++i) {
493            const sp<Layer>& layer(drawingLayers[i]);
494            if (layer.get() == static_cast<Layer const*>(this))
495                break;
496            under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
497        }
498        // if not everything below us is covered, we plug the holes!
499        Region holes(clip.subtract(under));
500        if (!holes.isEmpty()) {
501            clearWithOpenGL(hw, holes, 0, 0, 0, 1);
502        }
503        return;
504    }
505
506    // Bind the current buffer to the GL texture, and wait for it to be
507    // ready for us to draw into.
508    status_t err = mSurfaceFlingerConsumer->bindTextureImage();
509    if (err != NO_ERROR) {
510        ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
511        // Go ahead and draw the buffer anyway; no matter what we do the screen
512        // is probably going to have something visibly wrong.
513    }
514
515    bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
516
517    RenderEngine& engine(mFlinger->getRenderEngine());
518
519    if (!blackOutLayer) {
520        // TODO: we could be more subtle with isFixedSize()
521        const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
522
523        // Query the texture matrix given our current filtering mode.
524        float textureMatrix[16];
525        mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
526        mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
527
528        if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
529
530            /*
531             * the code below applies the display's inverse transform to the texture transform
532             */
533
534            // create a 4x4 transform matrix from the display transform flags
535            const mat4 flipH(-1,0,0,0,  0,1,0,0, 0,0,1,0, 1,0,0,1);
536            const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);
537            const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
538
539            mat4 tr;
540            uint32_t transform = hw->getOrientationTransform();
541            if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)
542                tr = tr * rot90;
543            if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H)
544                tr = tr * flipH;
545            if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V)
546                tr = tr * flipV;
547
548            // calculate the inverse
549            tr = inverse(tr);
550
551            // and finally apply it to the original texture matrix
552            const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
553            memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
554        }
555
556        // Set things up for texturing.
557        mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
558        mTexture.setFiltering(useFiltering);
559        mTexture.setMatrix(textureMatrix);
560
561        engine.setupLayerTexturing(mTexture);
562    } else {
563        engine.setupLayerBlackedOut();
564    }
565    drawWithOpenGL(hw, clip, useIdentityTransform);
566    engine.disableTexturing();
567}
568
569
570void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw,
571        const Region& /* clip */, float red, float green, float blue,
572        float alpha) const
573{
574    RenderEngine& engine(mFlinger->getRenderEngine());
575    computeGeometry(hw, mMesh, false);
576    engine.setupFillWithColor(red, green, blue, alpha);
577    engine.drawMesh(mMesh);
578}
579
580void Layer::clearWithOpenGL(
581        const sp<const DisplayDevice>& hw, const Region& clip) const {
582    clearWithOpenGL(hw, clip, 0,0,0,0);
583}
584
585void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
586        const Region& /* clip */, bool useIdentityTransform) const {
587    const uint32_t fbHeight = hw->getHeight();
588    const State& s(getDrawingState());
589
590    computeGeometry(hw, mMesh, useIdentityTransform);
591
592    /*
593     * NOTE: the way we compute the texture coordinates here produces
594     * different results than when we take the HWC path -- in the later case
595     * the "source crop" is rounded to texel boundaries.
596     * This can produce significantly different results when the texture
597     * is scaled by a large amount.
598     *
599     * The GL code below is more logical (imho), and the difference with
600     * HWC is due to a limitation of the HWC API to integers -- a question
601     * is suspend is whether we should ignore this problem or revert to
602     * GL composition when a buffer scaling is applied (maybe with some
603     * minimal value)? Or, we could make GL behave like HWC -- but this feel
604     * like more of a hack.
605     */
606    const Rect win(computeBounds());
607
608    float left   = float(win.left)   / float(s.active.w);
609    float top    = float(win.top)    / float(s.active.h);
610    float right  = float(win.right)  / float(s.active.w);
611    float bottom = float(win.bottom) / float(s.active.h);
612
613    // TODO: we probably want to generate the texture coords with the mesh
614    // here we assume that we only have 4 vertices
615    Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>());
616    texCoords[0] = vec2(left, 1.0f - top);
617    texCoords[1] = vec2(left, 1.0f - bottom);
618    texCoords[2] = vec2(right, 1.0f - bottom);
619    texCoords[3] = vec2(right, 1.0f - top);
620
621    RenderEngine& engine(mFlinger->getRenderEngine());
622    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
623    engine.drawMesh(mMesh);
624    engine.disableBlending();
625}
626
627uint32_t Layer::getProducerStickyTransform() const {
628    int producerStickyTransform = 0;
629    int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
630    if (ret != OK) {
631        ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
632                strerror(-ret), ret);
633        return 0;
634    }
635    return static_cast<uint32_t>(producerStickyTransform);
636}
637
638void Layer::setFiltering(bool filtering) {
639    mFiltering = filtering;
640}
641
642bool Layer::getFiltering() const {
643    return mFiltering;
644}
645
646// As documented in libhardware header, formats in the range
647// 0x100 - 0x1FF are specific to the HAL implementation, and
648// are known to have no alpha channel
649// TODO: move definition for device-specific range into
650// hardware.h, instead of using hard-coded values here.
651#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
652
653bool Layer::getOpacityForFormat(uint32_t format) {
654    if (HARDWARE_IS_DEVICE_FORMAT(format)) {
655        return true;
656    }
657    switch (format) {
658        case HAL_PIXEL_FORMAT_RGBA_8888:
659        case HAL_PIXEL_FORMAT_BGRA_8888:
660        case HAL_PIXEL_FORMAT_sRGB_A_8888:
661            return false;
662    }
663    // in all other case, we have no blending (also for unknown formats)
664    return true;
665}
666
667// ----------------------------------------------------------------------------
668// local state
669// ----------------------------------------------------------------------------
670
671void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
672        bool useIdentityTransform) const
673{
674    const Layer::State& s(getDrawingState());
675    const Transform tr(useIdentityTransform ?
676            hw->getTransform() : hw->getTransform() * s.transform);
677    const uint32_t hw_h = hw->getHeight();
678    Rect win(s.active.w, s.active.h);
679    if (!s.active.crop.isEmpty()) {
680        win.intersect(s.active.crop, &win);
681    }
682    // subtract the transparent region and snap to the bounds
683    win = reduce(win, s.activeTransparentRegion);
684
685    Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
686    position[0] = tr.transform(win.left,  win.top);
687    position[1] = tr.transform(win.left,  win.bottom);
688    position[2] = tr.transform(win.right, win.bottom);
689    position[3] = tr.transform(win.right, win.top);
690    for (size_t i=0 ; i<4 ; i++) {
691        position[i].y = hw_h - position[i].y;
692    }
693}
694
695bool Layer::isOpaque(const Layer::State& s) const
696{
697    // if we don't have a buffer yet, we're translucent regardless of the
698    // layer's opaque flag.
699    if (mActiveBuffer == 0) {
700        return false;
701    }
702
703    // if the layer has the opaque flag, then we're always opaque,
704    // otherwise we use the current buffer's format.
705    return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
706}
707
708bool Layer::isProtected() const
709{
710    const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
711    return (activeBuffer != 0) &&
712            (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
713}
714
715bool Layer::isFixedSize() const {
716    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
717}
718
719bool Layer::isCropped() const {
720    return !mCurrentCrop.isEmpty();
721}
722
723bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
724    return mNeedsFiltering || hw->needsFiltering();
725}
726
727void Layer::setVisibleRegion(const Region& visibleRegion) {
728    // always called from main thread
729    this->visibleRegion = visibleRegion;
730}
731
732void Layer::setCoveredRegion(const Region& coveredRegion) {
733    // always called from main thread
734    this->coveredRegion = coveredRegion;
735}
736
737void Layer::setVisibleNonTransparentRegion(const Region&
738        setVisibleNonTransparentRegion) {
739    // always called from main thread
740    this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
741}
742
743// ----------------------------------------------------------------------------
744// transaction
745// ----------------------------------------------------------------------------
746
747uint32_t Layer::doTransaction(uint32_t flags) {
748    ATRACE_CALL();
749
750    const Layer::State& s(getDrawingState());
751    const Layer::State& c(getCurrentState());
752
753    const bool sizeChanged = (c.requested.w != s.requested.w) ||
754                             (c.requested.h != s.requested.h);
755
756    if (sizeChanged) {
757        // the size changed, we need to ask our client to request a new buffer
758        ALOGD_IF(DEBUG_RESIZE,
759                "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
760                "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
761                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
762                "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
763                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
764                this, getName().string(), mCurrentTransform, mCurrentScalingMode,
765                c.active.w, c.active.h,
766                c.active.crop.left,
767                c.active.crop.top,
768                c.active.crop.right,
769                c.active.crop.bottom,
770                c.active.crop.getWidth(),
771                c.active.crop.getHeight(),
772                c.requested.w, c.requested.h,
773                c.requested.crop.left,
774                c.requested.crop.top,
775                c.requested.crop.right,
776                c.requested.crop.bottom,
777                c.requested.crop.getWidth(),
778                c.requested.crop.getHeight(),
779                s.active.w, s.active.h,
780                s.active.crop.left,
781                s.active.crop.top,
782                s.active.crop.right,
783                s.active.crop.bottom,
784                s.active.crop.getWidth(),
785                s.active.crop.getHeight(),
786                s.requested.w, s.requested.h,
787                s.requested.crop.left,
788                s.requested.crop.top,
789                s.requested.crop.right,
790                s.requested.crop.bottom,
791                s.requested.crop.getWidth(),
792                s.requested.crop.getHeight());
793
794        // record the new size, form this point on, when the client request
795        // a buffer, it'll get the new size.
796        mSurfaceFlingerConsumer->setDefaultBufferSize(
797                c.requested.w, c.requested.h);
798    }
799
800    if (!isFixedSize()) {
801
802        const bool resizePending = (c.requested.w != c.active.w) ||
803                                   (c.requested.h != c.active.h);
804
805        if (resizePending) {
806            // don't let Layer::doTransaction update the drawing state
807            // if we have a pending resize, unless we are in fixed-size mode.
808            // the drawing state will be updated only once we receive a buffer
809            // with the correct size.
810            //
811            // in particular, we want to make sure the clip (which is part
812            // of the geometry state) is latched together with the size but is
813            // latched immediately when no resizing is involved.
814
815            flags |= eDontUpdateGeometryState;
816        }
817    }
818
819    // always set active to requested, unless we're asked not to
820    // this is used by Layer, which special cases resizes.
821    if (flags & eDontUpdateGeometryState)  {
822    } else {
823        Layer::State& editCurrentState(getCurrentState());
824        editCurrentState.active = c.requested;
825    }
826
827    if (s.active != c.active) {
828        // invalidate and recompute the visible regions if needed
829        flags |= Layer::eVisibleRegion;
830    }
831
832    if (c.sequence != s.sequence) {
833        // invalidate and recompute the visible regions if needed
834        flags |= eVisibleRegion;
835        this->contentDirty = true;
836
837        // we may use linear filtering, if the matrix scales us
838        const uint8_t type = c.transform.getType();
839        mNeedsFiltering = (!c.transform.preserveRects() ||
840                (type >= Transform::SCALE));
841    }
842
843    // Commit the transaction
844    commitTransaction();
845    return flags;
846}
847
848void Layer::commitTransaction() {
849    mDrawingState = mCurrentState;
850}
851
852uint32_t Layer::getTransactionFlags(uint32_t flags) {
853    return android_atomic_and(~flags, &mTransactionFlags) & flags;
854}
855
856uint32_t Layer::setTransactionFlags(uint32_t flags) {
857    return android_atomic_or(flags, &mTransactionFlags);
858}
859
860bool Layer::setPosition(float x, float y) {
861    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
862        return false;
863    mCurrentState.sequence++;
864    mCurrentState.transform.set(x, y);
865    setTransactionFlags(eTransactionNeeded);
866    return true;
867}
868bool Layer::setLayer(uint32_t z) {
869    if (mCurrentState.z == z)
870        return false;
871    mCurrentState.sequence++;
872    mCurrentState.z = z;
873    setTransactionFlags(eTransactionNeeded);
874    return true;
875}
876bool Layer::setSize(uint32_t w, uint32_t h) {
877    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
878        return false;
879    mCurrentState.requested.w = w;
880    mCurrentState.requested.h = h;
881    setTransactionFlags(eTransactionNeeded);
882    return true;
883}
884bool Layer::setAlpha(uint8_t alpha) {
885    if (mCurrentState.alpha == alpha)
886        return false;
887    mCurrentState.sequence++;
888    mCurrentState.alpha = alpha;
889    setTransactionFlags(eTransactionNeeded);
890    return true;
891}
892bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
893    mCurrentState.sequence++;
894    mCurrentState.transform.set(
895            matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
896    setTransactionFlags(eTransactionNeeded);
897    return true;
898}
899bool Layer::setTransparentRegionHint(const Region& transparent) {
900    mCurrentState.requestedTransparentRegion = transparent;
901    setTransactionFlags(eTransactionNeeded);
902    return true;
903}
904bool Layer::setFlags(uint8_t flags, uint8_t mask) {
905    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
906    if (mCurrentState.flags == newFlags)
907        return false;
908    mCurrentState.sequence++;
909    mCurrentState.flags = newFlags;
910    setTransactionFlags(eTransactionNeeded);
911    return true;
912}
913bool Layer::setCrop(const Rect& crop) {
914    if (mCurrentState.requested.crop == crop)
915        return false;
916    mCurrentState.sequence++;
917    mCurrentState.requested.crop = crop;
918    setTransactionFlags(eTransactionNeeded);
919    return true;
920}
921
922bool Layer::setLayerStack(uint32_t layerStack) {
923    if (mCurrentState.layerStack == layerStack)
924        return false;
925    mCurrentState.sequence++;
926    mCurrentState.layerStack = layerStack;
927    setTransactionFlags(eTransactionNeeded);
928    return true;
929}
930
931// ----------------------------------------------------------------------------
932// pageflip handling...
933// ----------------------------------------------------------------------------
934
935bool Layer::onPreComposition() {
936    mRefreshPending = false;
937    return mQueuedFrames > 0 || mSidebandStreamChanged;
938}
939
940void Layer::onPostComposition() {
941    if (mFrameLatencyNeeded) {
942        nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
943        mFrameTracker.setDesiredPresentTime(desiredPresentTime);
944
945        sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence();
946        if (frameReadyFence->isValid()) {
947            mFrameTracker.setFrameReadyFence(frameReadyFence);
948        } else {
949            // There was no fence for this frame, so assume that it was ready
950            // to be presented at the desired present time.
951            mFrameTracker.setFrameReadyTime(desiredPresentTime);
952        }
953
954        const HWComposer& hwc = mFlinger->getHwComposer();
955        sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
956        if (presentFence->isValid()) {
957            mFrameTracker.setActualPresentFence(presentFence);
958        } else {
959            // The HWC doesn't support present fences, so use the refresh
960            // timestamp instead.
961            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
962            mFrameTracker.setActualPresentTime(presentTime);
963        }
964
965        mFrameTracker.advanceFrame();
966        mFrameLatencyNeeded = false;
967    }
968}
969
970bool Layer::isVisible() const {
971    const Layer::State& s(mDrawingState);
972    return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
973            && (mActiveBuffer != NULL || mSidebandStream != NULL);
974}
975
976Region Layer::latchBuffer(bool& recomputeVisibleRegions)
977{
978    ATRACE_CALL();
979
980    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
981        // mSidebandStreamChanged was true
982        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
983    }
984
985    Region outDirtyRegion;
986    if (mQueuedFrames > 0) {
987
988        // if we've already called updateTexImage() without going through
989        // a composition step, we have to skip this layer at this point
990        // because we cannot call updateTeximage() without a corresponding
991        // compositionComplete() call.
992        // we'll trigger an update in onPreComposition().
993        if (mRefreshPending) {
994            return outDirtyRegion;
995        }
996
997        // Capture the old state of the layer for comparisons later
998        const State& s(getDrawingState());
999        const bool oldOpacity = isOpaque(s);
1000        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
1001
1002        struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
1003            Layer::State& front;
1004            Layer::State& current;
1005            bool& recomputeVisibleRegions;
1006            bool stickyTransformSet;
1007            Reject(Layer::State& front, Layer::State& current,
1008                    bool& recomputeVisibleRegions, bool stickySet)
1009                : front(front), current(current),
1010                  recomputeVisibleRegions(recomputeVisibleRegions),
1011                  stickyTransformSet(stickySet) {
1012            }
1013
1014            virtual bool reject(const sp<GraphicBuffer>& buf,
1015                    const IGraphicBufferConsumer::BufferItem& item) {
1016                if (buf == NULL) {
1017                    return false;
1018                }
1019
1020                uint32_t bufWidth  = buf->getWidth();
1021                uint32_t bufHeight = buf->getHeight();
1022
1023                // check that we received a buffer of the right size
1024                // (Take the buffer's orientation into account)
1025                if (item.mTransform & Transform::ROT_90) {
1026                    swap(bufWidth, bufHeight);
1027                }
1028
1029                bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
1030                if (front.active != front.requested) {
1031
1032                    if (isFixedSize ||
1033                            (bufWidth == front.requested.w &&
1034                             bufHeight == front.requested.h))
1035                    {
1036                        // Here we pretend the transaction happened by updating the
1037                        // current and drawing states. Drawing state is only accessed
1038                        // in this thread, no need to have it locked
1039                        front.active = front.requested;
1040
1041                        // We also need to update the current state so that
1042                        // we don't end-up overwriting the drawing state with
1043                        // this stale current state during the next transaction
1044                        //
1045                        // NOTE: We don't need to hold the transaction lock here
1046                        // because State::active is only accessed from this thread.
1047                        current.active = front.active;
1048
1049                        // recompute visible region
1050                        recomputeVisibleRegions = true;
1051                    }
1052
1053                    ALOGD_IF(DEBUG_RESIZE,
1054                            "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
1055                            "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
1056                            "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
1057                            bufWidth, bufHeight, item.mTransform, item.mScalingMode,
1058                            front.active.w, front.active.h,
1059                            front.active.crop.left,
1060                            front.active.crop.top,
1061                            front.active.crop.right,
1062                            front.active.crop.bottom,
1063                            front.active.crop.getWidth(),
1064                            front.active.crop.getHeight(),
1065                            front.requested.w, front.requested.h,
1066                            front.requested.crop.left,
1067                            front.requested.crop.top,
1068                            front.requested.crop.right,
1069                            front.requested.crop.bottom,
1070                            front.requested.crop.getWidth(),
1071                            front.requested.crop.getHeight());
1072                }
1073
1074                if (!isFixedSize && !stickyTransformSet) {
1075                    if (front.active.w != bufWidth ||
1076                        front.active.h != bufHeight) {
1077                        // reject this buffer
1078                        ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
1079                                bufWidth, bufHeight, front.active.w, front.active.h);
1080                        return true;
1081                    }
1082                }
1083
1084                // if the transparent region has changed (this test is
1085                // conservative, but that's fine, worst case we're doing
1086                // a bit of extra work), we latch the new one and we
1087                // trigger a visible-region recompute.
1088                if (!front.activeTransparentRegion.isTriviallyEqual(
1089                        front.requestedTransparentRegion)) {
1090                    front.activeTransparentRegion = front.requestedTransparentRegion;
1091
1092                    // We also need to update the current state so that
1093                    // we don't end-up overwriting the drawing state with
1094                    // this stale current state during the next transaction
1095                    //
1096                    // NOTE: We don't need to hold the transaction lock here
1097                    // because State::active is only accessed from this thread.
1098                    current.activeTransparentRegion = front.activeTransparentRegion;
1099
1100                    // recompute visible region
1101                    recomputeVisibleRegions = true;
1102                }
1103
1104                return false;
1105            }
1106        };
1107
1108        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
1109                getProducerStickyTransform() != 0);
1110
1111        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
1112                mFlinger->mPrimaryDispSync);
1113        if (updateResult == BufferQueue::PRESENT_LATER) {
1114            // Producer doesn't want buffer to be displayed yet.  Signal a
1115            // layer update so we check again at the next opportunity.
1116            mFlinger->signalLayerUpdate();
1117            return outDirtyRegion;
1118        }
1119
1120        // Decrement the queued-frames count.  Signal another event if we
1121        // have more frames pending.
1122        if (android_atomic_dec(&mQueuedFrames) > 1) {
1123            mFlinger->signalLayerUpdate();
1124        }
1125
1126        if (updateResult != NO_ERROR) {
1127            // something happened!
1128            recomputeVisibleRegions = true;
1129            return outDirtyRegion;
1130        }
1131
1132        // update the active buffer
1133        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
1134        if (mActiveBuffer == NULL) {
1135            // this can only happen if the very first buffer was rejected.
1136            return outDirtyRegion;
1137        }
1138
1139        mRefreshPending = true;
1140        mFrameLatencyNeeded = true;
1141        if (oldActiveBuffer == NULL) {
1142             // the first time we receive a buffer, we need to trigger a
1143             // geometry invalidation.
1144            recomputeVisibleRegions = true;
1145         }
1146
1147        Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
1148        const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
1149        const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
1150        if ((crop != mCurrentCrop) ||
1151            (transform != mCurrentTransform) ||
1152            (scalingMode != mCurrentScalingMode))
1153        {
1154            mCurrentCrop = crop;
1155            mCurrentTransform = transform;
1156            mCurrentScalingMode = scalingMode;
1157            recomputeVisibleRegions = true;
1158        }
1159
1160        if (oldActiveBuffer != NULL) {
1161            uint32_t bufWidth  = mActiveBuffer->getWidth();
1162            uint32_t bufHeight = mActiveBuffer->getHeight();
1163            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
1164                bufHeight != uint32_t(oldActiveBuffer->height)) {
1165                recomputeVisibleRegions = true;
1166            }
1167        }
1168
1169        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
1170        if (oldOpacity != isOpaque(s)) {
1171            recomputeVisibleRegions = true;
1172        }
1173
1174        // FIXME: postedRegion should be dirty & bounds
1175        Region dirtyRegion(Rect(s.active.w, s.active.h));
1176
1177        // transform the dirty region to window-manager space
1178        outDirtyRegion = (s.transform.transform(dirtyRegion));
1179    }
1180    return outDirtyRegion;
1181}
1182
1183uint32_t Layer::getEffectiveUsage(uint32_t usage) const
1184{
1185    // TODO: should we do something special if mSecure is set?
1186    if (mProtectedByApp) {
1187        // need a hardware-protected path to external video sink
1188        usage |= GraphicBuffer::USAGE_PROTECTED;
1189    }
1190    usage |= GraphicBuffer::USAGE_HW_COMPOSER;
1191    return usage;
1192}
1193
1194void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
1195    uint32_t orientation = 0;
1196    if (!mFlinger->mDebugDisableTransformHint) {
1197        // The transform hint is used to improve performance, but we can
1198        // only have a single transform hint, it cannot
1199        // apply to all displays.
1200        const Transform& planeTransform(hw->getTransform());
1201        orientation = planeTransform.getOrientation();
1202        if (orientation & Transform::ROT_INVALID) {
1203            orientation = 0;
1204        }
1205    }
1206    mSurfaceFlingerConsumer->setTransformHint(orientation);
1207}
1208
1209// ----------------------------------------------------------------------------
1210// debugging
1211// ----------------------------------------------------------------------------
1212
1213void Layer::dump(String8& result, Colorizer& colorizer) const
1214{
1215    const Layer::State& s(getDrawingState());
1216
1217    colorizer.colorize(result, Colorizer::GREEN);
1218    result.appendFormat(
1219            "+ %s %p (%s)\n",
1220            getTypeId(), this, getName().string());
1221    colorizer.reset(result);
1222
1223    s.activeTransparentRegion.dump(result, "transparentRegion");
1224    visibleRegion.dump(result, "visibleRegion");
1225    sp<Client> client(mClientRef.promote());
1226
1227    result.appendFormat(            "      "
1228            "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
1229            "isOpaque=%1d, invalidate=%1d, "
1230            "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
1231            "      client=%p\n",
1232            s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
1233            s.active.crop.left, s.active.crop.top,
1234            s.active.crop.right, s.active.crop.bottom,
1235            isOpaque(s), contentDirty,
1236            s.alpha, s.flags,
1237            s.transform[0][0], s.transform[0][1],
1238            s.transform[1][0], s.transform[1][1],
1239            client.get());
1240
1241    sp<const GraphicBuffer> buf0(mActiveBuffer);
1242    uint32_t w0=0, h0=0, s0=0, f0=0;
1243    if (buf0 != 0) {
1244        w0 = buf0->getWidth();
1245        h0 = buf0->getHeight();
1246        s0 = buf0->getStride();
1247        f0 = buf0->format;
1248    }
1249    result.appendFormat(
1250            "      "
1251            "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
1252            " queued-frames=%d, mRefreshPending=%d\n",
1253            mFormat, w0, h0, s0,f0,
1254            mQueuedFrames, mRefreshPending);
1255
1256    if (mSurfaceFlingerConsumer != 0) {
1257        mSurfaceFlingerConsumer->dump(result, "            ");
1258    }
1259}
1260
1261void Layer::dumpFrameStats(String8& result) const {
1262    mFrameTracker.dumpStats(result);
1263}
1264
1265void Layer::clearFrameStats() {
1266    mFrameTracker.clearStats();
1267}
1268
1269void Layer::logFrameStats() {
1270    mFrameTracker.logAndResetStats(mName);
1271}
1272
1273void Layer::getFrameStats(FrameStats* outStats) const {
1274    mFrameTracker.getStats(outStats);
1275}
1276
1277// ---------------------------------------------------------------------------
1278
1279Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
1280        const sp<Layer>& layer)
1281    : mFlinger(flinger), mLayer(layer) {
1282}
1283
1284Layer::LayerCleaner::~LayerCleaner() {
1285    // destroy client resources
1286    mFlinger->onLayerDestroyed(mLayer);
1287}
1288
1289// ---------------------------------------------------------------------------
1290}; // namespace android
1291
1292#if defined(__gl_h_)
1293#error "don't include gl/gl.h in this file"
1294#endif
1295
1296#if defined(__gl2_h_)
1297#error "don't include gl2/gl2.h in this file"
1298#endif
1299