Layer.cpp revision d85084b2b65828442eafaff9b811e9b6c9ca9fad
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<BnGraphicBufferProducer> producer;
121    sp<BnGraphicBufferConsumer> 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
627void Layer::setFiltering(bool filtering) {
628    mFiltering = filtering;
629}
630
631bool Layer::getFiltering() const {
632    return mFiltering;
633}
634
635// As documented in libhardware header, formats in the range
636// 0x100 - 0x1FF are specific to the HAL implementation, and
637// are known to have no alpha channel
638// TODO: move definition for device-specific range into
639// hardware.h, instead of using hard-coded values here.
640#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
641
642bool Layer::getOpacityForFormat(uint32_t format) {
643    if (HARDWARE_IS_DEVICE_FORMAT(format)) {
644        return true;
645    }
646    switch (format) {
647        case HAL_PIXEL_FORMAT_RGBA_8888:
648        case HAL_PIXEL_FORMAT_BGRA_8888:
649        case HAL_PIXEL_FORMAT_sRGB_A_8888:
650            return false;
651    }
652    // in all other case, we have no blending (also for unknown formats)
653    return true;
654}
655
656// ----------------------------------------------------------------------------
657// local state
658// ----------------------------------------------------------------------------
659
660void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
661        bool useIdentityTransform) const
662{
663    const Layer::State& s(getDrawingState());
664    const Transform tr(useIdentityTransform ?
665            hw->getTransform() : hw->getTransform() * s.transform);
666    const uint32_t hw_h = hw->getHeight();
667    Rect win(s.active.w, s.active.h);
668    if (!s.active.crop.isEmpty()) {
669        win.intersect(s.active.crop, &win);
670    }
671    // subtract the transparent region and snap to the bounds
672    win = reduce(win, s.activeTransparentRegion);
673
674    Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
675    position[0] = tr.transform(win.left,  win.top);
676    position[1] = tr.transform(win.left,  win.bottom);
677    position[2] = tr.transform(win.right, win.bottom);
678    position[3] = tr.transform(win.right, win.top);
679    for (size_t i=0 ; i<4 ; i++) {
680        position[i].y = hw_h - position[i].y;
681    }
682}
683
684bool Layer::isOpaque(const Layer::State& s) const
685{
686    // if we don't have a buffer yet, we're translucent regardless of the
687    // layer's opaque flag.
688    if (mActiveBuffer == 0) {
689        return false;
690    }
691
692    // if the layer has the opaque flag, then we're always opaque,
693    // otherwise we use the current buffer's format.
694    return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
695}
696
697bool Layer::isProtected() const
698{
699    const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
700    return (activeBuffer != 0) &&
701            (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
702}
703
704bool Layer::isFixedSize() const {
705    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
706}
707
708bool Layer::isCropped() const {
709    return !mCurrentCrop.isEmpty();
710}
711
712bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
713    return mNeedsFiltering || hw->needsFiltering();
714}
715
716void Layer::setVisibleRegion(const Region& visibleRegion) {
717    // always called from main thread
718    this->visibleRegion = visibleRegion;
719}
720
721void Layer::setCoveredRegion(const Region& coveredRegion) {
722    // always called from main thread
723    this->coveredRegion = coveredRegion;
724}
725
726void Layer::setVisibleNonTransparentRegion(const Region&
727        setVisibleNonTransparentRegion) {
728    // always called from main thread
729    this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
730}
731
732// ----------------------------------------------------------------------------
733// transaction
734// ----------------------------------------------------------------------------
735
736uint32_t Layer::doTransaction(uint32_t flags) {
737    ATRACE_CALL();
738
739    const Layer::State& s(getDrawingState());
740    const Layer::State& c(getCurrentState());
741
742    const bool sizeChanged = (c.requested.w != s.requested.w) ||
743                             (c.requested.h != s.requested.h);
744
745    if (sizeChanged) {
746        // the size changed, we need to ask our client to request a new buffer
747        ALOGD_IF(DEBUG_RESIZE,
748                "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
749                "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
750                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
751                "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
752                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
753                this, getName().string(), mCurrentTransform, mCurrentScalingMode,
754                c.active.w, c.active.h,
755                c.active.crop.left,
756                c.active.crop.top,
757                c.active.crop.right,
758                c.active.crop.bottom,
759                c.active.crop.getWidth(),
760                c.active.crop.getHeight(),
761                c.requested.w, c.requested.h,
762                c.requested.crop.left,
763                c.requested.crop.top,
764                c.requested.crop.right,
765                c.requested.crop.bottom,
766                c.requested.crop.getWidth(),
767                c.requested.crop.getHeight(),
768                s.active.w, s.active.h,
769                s.active.crop.left,
770                s.active.crop.top,
771                s.active.crop.right,
772                s.active.crop.bottom,
773                s.active.crop.getWidth(),
774                s.active.crop.getHeight(),
775                s.requested.w, s.requested.h,
776                s.requested.crop.left,
777                s.requested.crop.top,
778                s.requested.crop.right,
779                s.requested.crop.bottom,
780                s.requested.crop.getWidth(),
781                s.requested.crop.getHeight());
782
783        // record the new size, form this point on, when the client request
784        // a buffer, it'll get the new size.
785        mSurfaceFlingerConsumer->setDefaultBufferSize(
786                c.requested.w, c.requested.h);
787    }
788
789    if (!isFixedSize()) {
790
791        const bool resizePending = (c.requested.w != c.active.w) ||
792                                   (c.requested.h != c.active.h);
793
794        if (resizePending) {
795            // don't let Layer::doTransaction update the drawing state
796            // if we have a pending resize, unless we are in fixed-size mode.
797            // the drawing state will be updated only once we receive a buffer
798            // with the correct size.
799            //
800            // in particular, we want to make sure the clip (which is part
801            // of the geometry state) is latched together with the size but is
802            // latched immediately when no resizing is involved.
803
804            flags |= eDontUpdateGeometryState;
805        }
806    }
807
808    // always set active to requested, unless we're asked not to
809    // this is used by Layer, which special cases resizes.
810    if (flags & eDontUpdateGeometryState)  {
811    } else {
812        Layer::State& editCurrentState(getCurrentState());
813        editCurrentState.active = c.requested;
814    }
815
816    if (s.active != c.active) {
817        // invalidate and recompute the visible regions if needed
818        flags |= Layer::eVisibleRegion;
819    }
820
821    if (c.sequence != s.sequence) {
822        // invalidate and recompute the visible regions if needed
823        flags |= eVisibleRegion;
824        this->contentDirty = true;
825
826        // we may use linear filtering, if the matrix scales us
827        const uint8_t type = c.transform.getType();
828        mNeedsFiltering = (!c.transform.preserveRects() ||
829                (type >= Transform::SCALE));
830    }
831
832    // Commit the transaction
833    commitTransaction();
834    return flags;
835}
836
837void Layer::commitTransaction() {
838    mDrawingState = mCurrentState;
839}
840
841uint32_t Layer::getTransactionFlags(uint32_t flags) {
842    return android_atomic_and(~flags, &mTransactionFlags) & flags;
843}
844
845uint32_t Layer::setTransactionFlags(uint32_t flags) {
846    return android_atomic_or(flags, &mTransactionFlags);
847}
848
849bool Layer::setPosition(float x, float y) {
850    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
851        return false;
852    mCurrentState.sequence++;
853    mCurrentState.transform.set(x, y);
854    setTransactionFlags(eTransactionNeeded);
855    return true;
856}
857bool Layer::setLayer(uint32_t z) {
858    if (mCurrentState.z == z)
859        return false;
860    mCurrentState.sequence++;
861    mCurrentState.z = z;
862    setTransactionFlags(eTransactionNeeded);
863    return true;
864}
865bool Layer::setSize(uint32_t w, uint32_t h) {
866    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
867        return false;
868    mCurrentState.requested.w = w;
869    mCurrentState.requested.h = h;
870    setTransactionFlags(eTransactionNeeded);
871    return true;
872}
873bool Layer::setAlpha(uint8_t alpha) {
874    if (mCurrentState.alpha == alpha)
875        return false;
876    mCurrentState.sequence++;
877    mCurrentState.alpha = alpha;
878    setTransactionFlags(eTransactionNeeded);
879    return true;
880}
881bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
882    mCurrentState.sequence++;
883    mCurrentState.transform.set(
884            matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
885    setTransactionFlags(eTransactionNeeded);
886    return true;
887}
888bool Layer::setTransparentRegionHint(const Region& transparent) {
889    mCurrentState.requestedTransparentRegion = transparent;
890    setTransactionFlags(eTransactionNeeded);
891    return true;
892}
893bool Layer::setFlags(uint8_t flags, uint8_t mask) {
894    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
895    if (mCurrentState.flags == newFlags)
896        return false;
897    mCurrentState.sequence++;
898    mCurrentState.flags = newFlags;
899    setTransactionFlags(eTransactionNeeded);
900    return true;
901}
902bool Layer::setCrop(const Rect& crop) {
903    if (mCurrentState.requested.crop == crop)
904        return false;
905    mCurrentState.sequence++;
906    mCurrentState.requested.crop = crop;
907    setTransactionFlags(eTransactionNeeded);
908    return true;
909}
910
911bool Layer::setLayerStack(uint32_t layerStack) {
912    if (mCurrentState.layerStack == layerStack)
913        return false;
914    mCurrentState.sequence++;
915    mCurrentState.layerStack = layerStack;
916    setTransactionFlags(eTransactionNeeded);
917    return true;
918}
919
920// ----------------------------------------------------------------------------
921// pageflip handling...
922// ----------------------------------------------------------------------------
923
924bool Layer::onPreComposition() {
925    mRefreshPending = false;
926    return mQueuedFrames > 0 || mSidebandStreamChanged;
927}
928
929void Layer::onPostComposition() {
930    if (mFrameLatencyNeeded) {
931        nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
932        mFrameTracker.setDesiredPresentTime(desiredPresentTime);
933
934        sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence();
935        if (frameReadyFence->isValid()) {
936            mFrameTracker.setFrameReadyFence(frameReadyFence);
937        } else {
938            // There was no fence for this frame, so assume that it was ready
939            // to be presented at the desired present time.
940            mFrameTracker.setFrameReadyTime(desiredPresentTime);
941        }
942
943        const HWComposer& hwc = mFlinger->getHwComposer();
944        sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
945        if (presentFence->isValid()) {
946            mFrameTracker.setActualPresentFence(presentFence);
947        } else {
948            // The HWC doesn't support present fences, so use the refresh
949            // timestamp instead.
950            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
951            mFrameTracker.setActualPresentTime(presentTime);
952        }
953
954        mFrameTracker.advanceFrame();
955        mFrameLatencyNeeded = false;
956    }
957}
958
959bool Layer::isVisible() const {
960    const Layer::State& s(mDrawingState);
961    return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
962            && (mActiveBuffer != NULL);
963}
964
965Region Layer::latchBuffer(bool& recomputeVisibleRegions)
966{
967    ATRACE_CALL();
968
969    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
970        // mSidebandStreamChanged was true
971        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
972    }
973
974    Region outDirtyRegion;
975    if (mQueuedFrames > 0) {
976
977        // if we've already called updateTexImage() without going through
978        // a composition step, we have to skip this layer at this point
979        // because we cannot call updateTeximage() without a corresponding
980        // compositionComplete() call.
981        // we'll trigger an update in onPreComposition().
982        if (mRefreshPending) {
983            return outDirtyRegion;
984        }
985
986        // Capture the old state of the layer for comparisons later
987        const State& s(getDrawingState());
988        const bool oldOpacity = isOpaque(s);
989        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
990
991        struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
992            Layer::State& front;
993            Layer::State& current;
994            bool& recomputeVisibleRegions;
995            Reject(Layer::State& front, Layer::State& current,
996                    bool& recomputeVisibleRegions)
997                : front(front), current(current),
998                  recomputeVisibleRegions(recomputeVisibleRegions) {
999            }
1000
1001            virtual bool reject(const sp<GraphicBuffer>& buf,
1002                    const IGraphicBufferConsumer::BufferItem& item) {
1003                if (buf == NULL) {
1004                    return false;
1005                }
1006
1007                uint32_t bufWidth  = buf->getWidth();
1008                uint32_t bufHeight = buf->getHeight();
1009
1010                // check that we received a buffer of the right size
1011                // (Take the buffer's orientation into account)
1012                if (item.mTransform & Transform::ROT_90) {
1013                    swap(bufWidth, bufHeight);
1014                }
1015
1016                bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
1017                if (front.active != front.requested) {
1018
1019                    if (isFixedSize ||
1020                            (bufWidth == front.requested.w &&
1021                             bufHeight == front.requested.h))
1022                    {
1023                        // Here we pretend the transaction happened by updating the
1024                        // current and drawing states. Drawing state is only accessed
1025                        // in this thread, no need to have it locked
1026                        front.active = front.requested;
1027
1028                        // We also need to update the current state so that
1029                        // we don't end-up overwriting the drawing state with
1030                        // this stale current state during the next transaction
1031                        //
1032                        // NOTE: We don't need to hold the transaction lock here
1033                        // because State::active is only accessed from this thread.
1034                        current.active = front.active;
1035
1036                        // recompute visible region
1037                        recomputeVisibleRegions = true;
1038                    }
1039
1040                    ALOGD_IF(DEBUG_RESIZE,
1041                            "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
1042                            "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
1043                            "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
1044                            bufWidth, bufHeight, item.mTransform, item.mScalingMode,
1045                            front.active.w, front.active.h,
1046                            front.active.crop.left,
1047                            front.active.crop.top,
1048                            front.active.crop.right,
1049                            front.active.crop.bottom,
1050                            front.active.crop.getWidth(),
1051                            front.active.crop.getHeight(),
1052                            front.requested.w, front.requested.h,
1053                            front.requested.crop.left,
1054                            front.requested.crop.top,
1055                            front.requested.crop.right,
1056                            front.requested.crop.bottom,
1057                            front.requested.crop.getWidth(),
1058                            front.requested.crop.getHeight());
1059                }
1060
1061                if (!isFixedSize) {
1062                    if (front.active.w != bufWidth ||
1063                        front.active.h != bufHeight) {
1064                        // reject this buffer
1065                        //ALOGD("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
1066                        //        bufWidth, bufHeight, front.active.w, front.active.h);
1067                        return true;
1068                    }
1069                }
1070
1071                // if the transparent region has changed (this test is
1072                // conservative, but that's fine, worst case we're doing
1073                // a bit of extra work), we latch the new one and we
1074                // trigger a visible-region recompute.
1075                if (!front.activeTransparentRegion.isTriviallyEqual(
1076                        front.requestedTransparentRegion)) {
1077                    front.activeTransparentRegion = front.requestedTransparentRegion;
1078
1079                    // We also need to update the current state so that
1080                    // we don't end-up overwriting the drawing state with
1081                    // this stale current state during the next transaction
1082                    //
1083                    // NOTE: We don't need to hold the transaction lock here
1084                    // because State::active is only accessed from this thread.
1085                    current.activeTransparentRegion = front.activeTransparentRegion;
1086
1087                    // recompute visible region
1088                    recomputeVisibleRegions = true;
1089                }
1090
1091                return false;
1092            }
1093        };
1094
1095
1096        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions);
1097
1098        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r);
1099        if (updateResult == BufferQueue::PRESENT_LATER) {
1100            // Producer doesn't want buffer to be displayed yet.  Signal a
1101            // layer update so we check again at the next opportunity.
1102            mFlinger->signalLayerUpdate();
1103            return outDirtyRegion;
1104        }
1105
1106        // Decrement the queued-frames count.  Signal another event if we
1107        // have more frames pending.
1108        if (android_atomic_dec(&mQueuedFrames) > 1) {
1109            mFlinger->signalLayerUpdate();
1110        }
1111
1112        if (updateResult != NO_ERROR) {
1113            // something happened!
1114            recomputeVisibleRegions = true;
1115            return outDirtyRegion;
1116        }
1117
1118        // update the active buffer
1119        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
1120        if (mActiveBuffer == NULL) {
1121            // this can only happen if the very first buffer was rejected.
1122            return outDirtyRegion;
1123        }
1124
1125        mRefreshPending = true;
1126        mFrameLatencyNeeded = true;
1127        if (oldActiveBuffer == NULL) {
1128             // the first time we receive a buffer, we need to trigger a
1129             // geometry invalidation.
1130            recomputeVisibleRegions = true;
1131         }
1132
1133        Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
1134        const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
1135        const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
1136        if ((crop != mCurrentCrop) ||
1137            (transform != mCurrentTransform) ||
1138            (scalingMode != mCurrentScalingMode))
1139        {
1140            mCurrentCrop = crop;
1141            mCurrentTransform = transform;
1142            mCurrentScalingMode = scalingMode;
1143            recomputeVisibleRegions = true;
1144        }
1145
1146        if (oldActiveBuffer != NULL) {
1147            uint32_t bufWidth  = mActiveBuffer->getWidth();
1148            uint32_t bufHeight = mActiveBuffer->getHeight();
1149            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
1150                bufHeight != uint32_t(oldActiveBuffer->height)) {
1151                recomputeVisibleRegions = true;
1152            }
1153        }
1154
1155        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
1156        if (oldOpacity != isOpaque(s)) {
1157            recomputeVisibleRegions = true;
1158        }
1159
1160        // FIXME: postedRegion should be dirty & bounds
1161        Region dirtyRegion(Rect(s.active.w, s.active.h));
1162
1163        // transform the dirty region to window-manager space
1164        outDirtyRegion = (s.transform.transform(dirtyRegion));
1165    }
1166    return outDirtyRegion;
1167}
1168
1169uint32_t Layer::getEffectiveUsage(uint32_t usage) const
1170{
1171    // TODO: should we do something special if mSecure is set?
1172    if (mProtectedByApp) {
1173        // need a hardware-protected path to external video sink
1174        usage |= GraphicBuffer::USAGE_PROTECTED;
1175    }
1176    usage |= GraphicBuffer::USAGE_HW_COMPOSER;
1177    return usage;
1178}
1179
1180void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
1181    uint32_t orientation = 0;
1182    if (!mFlinger->mDebugDisableTransformHint) {
1183        // The transform hint is used to improve performance, but we can
1184        // only have a single transform hint, it cannot
1185        // apply to all displays.
1186        const Transform& planeTransform(hw->getTransform());
1187        orientation = planeTransform.getOrientation();
1188        if (orientation & Transform::ROT_INVALID) {
1189            orientation = 0;
1190        }
1191    }
1192    mSurfaceFlingerConsumer->setTransformHint(orientation);
1193}
1194
1195// ----------------------------------------------------------------------------
1196// debugging
1197// ----------------------------------------------------------------------------
1198
1199void Layer::dump(String8& result, Colorizer& colorizer) const
1200{
1201    const Layer::State& s(getDrawingState());
1202
1203    colorizer.colorize(result, Colorizer::GREEN);
1204    result.appendFormat(
1205            "+ %s %p (%s)\n",
1206            getTypeId(), this, getName().string());
1207    colorizer.reset(result);
1208
1209    s.activeTransparentRegion.dump(result, "transparentRegion");
1210    visibleRegion.dump(result, "visibleRegion");
1211    sp<Client> client(mClientRef.promote());
1212
1213    result.appendFormat(            "      "
1214            "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
1215            "isOpaque=%1d, invalidate=%1d, "
1216            "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
1217            "      client=%p\n",
1218            s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
1219            s.active.crop.left, s.active.crop.top,
1220            s.active.crop.right, s.active.crop.bottom,
1221            isOpaque(s), contentDirty,
1222            s.alpha, s.flags,
1223            s.transform[0][0], s.transform[0][1],
1224            s.transform[1][0], s.transform[1][1],
1225            client.get());
1226
1227    sp<const GraphicBuffer> buf0(mActiveBuffer);
1228    uint32_t w0=0, h0=0, s0=0, f0=0;
1229    if (buf0 != 0) {
1230        w0 = buf0->getWidth();
1231        h0 = buf0->getHeight();
1232        s0 = buf0->getStride();
1233        f0 = buf0->format;
1234    }
1235    result.appendFormat(
1236            "      "
1237            "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
1238            " queued-frames=%d, mRefreshPending=%d\n",
1239            mFormat, w0, h0, s0,f0,
1240            mQueuedFrames, mRefreshPending);
1241
1242    if (mSurfaceFlingerConsumer != 0) {
1243        mSurfaceFlingerConsumer->dump(result, "            ");
1244    }
1245}
1246
1247void Layer::dumpFrameStats(String8& result) const {
1248    mFrameTracker.dumpStats(result);
1249}
1250
1251void Layer::clearFrameStats() {
1252    mFrameTracker.clearStats();
1253}
1254
1255void Layer::logFrameStats() {
1256    mFrameTracker.logAndResetStats(mName);
1257}
1258
1259void Layer::getFrameStats(FrameStats* outStats) const {
1260    mFrameTracker.getStats(outStats);
1261}
1262
1263// ---------------------------------------------------------------------------
1264
1265Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
1266        const sp<Layer>& layer)
1267    : mFlinger(flinger), mLayer(layer) {
1268}
1269
1270Layer::LayerCleaner::~LayerCleaner() {
1271    // destroy client resources
1272    mFlinger->onLayerDestroyed(mLayer);
1273}
1274
1275// ---------------------------------------------------------------------------
1276}; // namespace android
1277
1278#if defined(__gl_h_)
1279#error "don't include gl/gl.h in this file"
1280#endif
1281
1282#if defined(__gl2_h_)
1283#error "don't include gl2/gl2.h in this file"
1284#endif
1285