Layer.cpp revision 31a353da225af5329735451c761b430d82dfda1b
17532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor/*
27532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * Copyright (C) 2007 The Android Open Source Project
37532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor *
47532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * Licensed under the Apache License, Version 2.0 (the "License");
57532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * you may not use this file except in compliance with the License.
67532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * You may obtain a copy of the License at
77532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor *
87532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor *      http://www.apache.org/licenses/LICENSE-2.0
97532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor *
107532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * Unless required by applicable law or agreed to in writing, software
117532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * distributed under the License is distributed on an "AS IS" BASIS,
127532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * See the License for the specific language governing permissions and
147532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor * limitations under the License.
157532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor */
167532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
178cc488fefb2fb04bc8d5398da29f0182f97934cfChris Lattner#define ATRACE_TAG ATRACE_TAG_GRAPHICS
187532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
197532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <stdlib.h>
207532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <stdint.h>
217532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <sys/types.h>
221aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include <math.h>
231aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
247532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <cutils/compiler.h>
25db88d8ad74097e2601d81ee863ce46a8a48a7034Jeffrey Yasskin#include <cutils/native_handle.h>
267532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <cutils/properties.h>
276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
287532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <utils/Errors.h>
296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include <utils/Log.h>
301aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include <utils/StopWatch.h>
313b4ea54acf01f72f6eb74d96689dda86d950228fDaniel Dunbar#include <utils/Trace.h>
327532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
331aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include <ui/GraphicBuffer.h>
346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include <ui/PixelFormat.h>
351aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
367532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#include <gui/Surface.h>
371aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
381aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include "clz.h"
391aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include "DisplayDevice.h"
401aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include "GLExtensions.h"
411aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include "Layer.h"
421aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor#include "SurfaceFlinger.h"
43146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall#include "SurfaceTextureLayer.h"
44146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
45146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall#include "DisplayHardware/HWComposer.h"
46146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
47146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall#define DEBUG_RESIZE    0
48146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
49e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christophernamespace android {
50e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher
51e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher// ---------------------------------------------------------------------------
521aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
53e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric ChristopherLayer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
54e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher    :   LayerBaseClient(flinger, client),
55e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher        mTextureName(-1U),
56e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher        mQueuedFrames(0),
57e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher        mCurrentTransform(0),
58e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
59e462c60ac3365d3302b7d0a566c5cb7dbe0e5ae3Eric Christopher        mCurrentOpacity(true),
609c34ee65a61bbfb60ae76d4df674f49df1842e70Douglas Gregor        mRefreshPending(false),
610bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall        mFrameLatencyNeeded(false),
629c34ee65a61bbfb60ae76d4df674f49df1842e70Douglas Gregor        mFrameLatencyOffset(0),
63146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        mFormat(PIXEL_FORMAT_NONE),
64146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        mGLExtensions(GLExtensions::getInstance()),
65146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        mOpaqueLayer(true),
661aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        mSecure(false),
671aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        mProtectedByApp(false)
681aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor{
691aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    mCurrentCrop.makeInvalid();
701aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    glGenTextures(1, &mTextureName);
711aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor}
72146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
731aee05d08b2184acadeb36de300e216390780d6cDouglas Gregorvoid Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        HWComposer::HWCLayerInterface* layer) {
751aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    if (layer) {
761aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
77146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    }
78146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall}
79146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid Layer::onFirstRef()
81146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall{
82146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    LayerBaseClient::onFirstRef();
831aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
84146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
85146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        FrameQueuedListener(Layer* layer) : mLayer(layer) { }
866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    private:
871aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        wp<Layer> mLayer;
881aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        virtual void onFrameAvailable() {
891aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor            sp<Layer> that(mLayer.promote());
901aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor            if (that != 0) {
911aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor                that->onFrameQueued();
921aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor            }
930bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall        }
940bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    };
95146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
96146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    // Creates a custom BufferQueue for SurfaceTexture to use
970bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    sp<BufferQueue> bq = new SurfaceTextureLayer();
980bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    mSurfaceTexture = new SurfaceTexture(mTextureName, true,
999c34ee65a61bbfb60ae76d4df674f49df1842e70Douglas Gregor            GL_TEXTURE_EXTERNAL_OES, false, bq);
1000bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall
1010bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
1029c34ee65a61bbfb60ae76d4df674f49df1842e70Douglas Gregor    mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
1030bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    mSurfaceTexture->setSynchronousMode(true);
1040bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall
1050bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
1060bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall#warning "disabling triple buffering"
1070bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    mSurfaceTexture->setDefaultMaxBufferCount(2);
1080bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall#else
1090bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    mSurfaceTexture->setDefaultMaxBufferCount(3);
1100bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall#endif
111146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall}
1121aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
1131aee05d08b2184acadeb36de300e216390780d6cDouglas GregorLayer::~Layer()
1141aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor{
1151aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    mFlinger->deleteTextureAsync(mTextureName);
1161aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor}
1171aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
1181aee05d08b2184acadeb36de300e216390780d6cDouglas Gregorvoid Layer::onFrameQueued() {
1191aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    android_atomic_inc(&mQueuedFrames);
1201aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    mFlinger->signalLayerUpdate();
1211aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor}
1221aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
1231aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor// called with SurfaceFlinger::mStateLock as soon as the layer is entered
1241aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor// in the purgatory list
125146060435c3efce95c95a092c7a1eb651cfb9ae0John McCallvoid Layer::onRemoved()
1261aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor{
1271aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    mSurfaceTexture->abandon();
128146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall}
1291aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
1301aee05d08b2184acadeb36de300e216390780d6cDouglas Gregorvoid Layer::setName(const String8& name) {
1311aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    LayerBase::setName(name);
1321aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    mSurfaceTexture->setName(name);
1331aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor}
1341aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
1351aee05d08b2184acadeb36de300e216390780d6cDouglas Gregorsp<ISurface> Layer::createSurface()
1361aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor{
1371aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    class BSurface : public BnSurface, public LayerCleaner {
1381aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        wp<const Layer> mOwner;
1391aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        virtual sp<ISurfaceTexture> getSurfaceTexture() const {
140146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall            sp<ISurfaceTexture> res;
1411aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor            sp<const Layer> that( mOwner.promote() );
142146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall            if (that != NULL) {
143146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall                res = that->mSurfaceTexture->getBufferQueue();
1441aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor            }
1451aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor            return res;
1461aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        }
1477532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    public:
1487532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        BSurface(const sp<SurfaceFlinger>& flinger,
1497532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                const sp<Layer>& layer)
1507532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            : LayerCleaner(flinger, layer), mOwner(layer) { }
1517532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    };
1527532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    sp<ISurface> sur(new BSurface(mFlinger, this));
1537532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    return sur;
1547532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
1557532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
1567532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorwp<IBinder> Layer::getSurfaceTextureBinder() const
1577532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor{
1587532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    return mSurfaceTexture->getBufferQueue()->asBinder();
1597532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
1607532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
1617532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorstatus_t Layer::setBuffers( uint32_t w, uint32_t h,
1627532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                            PixelFormat format, uint32_t flags)
1637532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor{
1647532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // this surfaces pixel format
1657532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    PixelFormatInfo info;
1667532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    status_t err = getPixelFormatInfo(format, &info);
1677532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    if (err) {
1687532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        ALOGE("unsupported pixelformat %d", format);
1697532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        return err;
1707532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    }
1717532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
1727532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    uint32_t const maxSurfaceDims = min(
1737532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
1747532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
1757532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // never allow a surface larger than what our underlying GL implementation
1760bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    // can handle.
1771aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
1781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
1797532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        return BAD_VALUE;
1807532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    }
1817532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
1827532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    mFormat = format;
1837532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
1847532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
1857532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
1867532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
1877532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    mCurrentOpacity = getOpacityForFormat(format);
18890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
18990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    mSurfaceTexture->setDefaultBufferSize(w, h);
1901aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    mSurfaceTexture->setDefaultBufferFormat(format);
19190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
1921aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
19390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    return NO_ERROR;
1941aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor}
1951aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
19690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios KyrtzidisRect Layer::computeBufferCrop() const {
1971aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    // Start with the SurfaceTexture's buffer crop...
1981aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    Rect crop;
1991aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    if (!mCurrentCrop.isEmpty()) {
200146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        crop = mCurrentCrop;
201146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    } else  if (mActiveBuffer != NULL){
202146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
2031aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    } else {
2041aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        crop.makeInvalid();
2051aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        return crop;
2061aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    }
20790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
20890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    // ... then reduce that in the same proportions as the window crop reduces
2097532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // the window size.
2107532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    const State& s(drawingState());
2110bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    if (!s.active.crop.isEmpty()) {
2120bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall        // Transform the window crop to match the buffer coordinate system,
213146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        // which means using the inverse of the current transform set on the
2141aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        // SurfaceTexture.
2151aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        uint32_t invTransform = mCurrentTransform;
2167532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        int winWidth = s.active.w;
2177532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        int winHeight = s.active.h;
2187532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
219577f75a7498e9e2536434da0ef0da0eea390d18bDouglas Gregor            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
220577f75a7498e9e2536434da0ef0da0eea390d18bDouglas Gregor                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
22190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis            winWidth = s.active.h;
22290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis            winHeight = s.active.w;
22390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis        }
2241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        Rect winCrop = s.active.crop.transform(invTransform,
2251aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor                s.active.w, s.active.h);
2267532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
2277532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        float xScale = float(crop.width()) / float(winWidth);
2287532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        float yScale = float(crop.height()) / float(winHeight);
2297532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        crop.left += int(ceilf(float(winCrop.left) * xScale));
2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        crop.top += int(ceilf(float(winCrop.top) * yScale));
231d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor        crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
2327532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
2337532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    }
2341aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
235d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor    return crop;
236d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor}
2371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Layer::setGeometry(
239d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor    const sp<const DisplayDevice>& hw,
240d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor        HWComposer::HWCLayerInterface& layer)
2410bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall{
2421aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    LayerBaseClient::setGeometry(hw, layer);
2431aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
2441aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    // enable this layer
2451aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    layer.setSkip(false);
2466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2471aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    // we can't do alpha-fade with the hwc HAL
2481aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    const State& s(drawingState());
249146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    if (s.alpha < 0xFF) {
250146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        layer.setSkip(true);
251146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    }
252146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
253146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    /*
254146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall     * Transformations are applied in this order:
255146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall     * 1) buffer orientation/flip/mirror
256146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall     * 2) state transformation (window manager)
257146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall     * 3) layer orientation (screen orientation)
258146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall     * (NOTE: the matrices are multiplied in reverse order)
2596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines     */
260146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
261146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    const Transform bufferOrientation(mCurrentTransform);
2621aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
2631aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
2641aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    // this gives us only the "orientation" component of the transform
2651aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    const uint32_t finalTransform = tr.getOrientation();
2661aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor
2671aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    // we can only handle simple transformation
2681aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    if (finalTransform & Transform::ROT_INVALID) {
2691aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        layer.setSkip(true);
2701aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    } else {
2711aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor        layer.setTransform(finalTransform);
2721aee05d08b2184acadeb36de300e216390780d6cDouglas Gregor    }
2736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    layer.setCrop(computeBufferCrop());
2740bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall}
2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2767532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorvoid Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
2777532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        HWComposer::HWCLayerInterface& layer) {
2787532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    const sp<GraphicBuffer>& buffer(mActiveBuffer);
2797532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // NOTE: buffer can be NULL if the client never drew into this
2807532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // layer yet, or if we ran out of memory
2817532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    layer.setBuffer(buffer);
2827532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
2837532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
2847532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorvoid Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
2857532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        HWComposer::HWCLayerInterface& layer) {
2867532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    int fenceFd = -1;
2877532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
288146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    // TODO: there is a possible optimization here: we only need to set the
289146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    // acquire fence the first time a new buffer is acquired on EACH display.
2907532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
2917532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    if (layer.getCompositionType() == HWC_OVERLAY) {
2927532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        sp<Fence> fence = mSurfaceTexture->getCurrentFence();
293561f81243f665cf2001caadc45df505f826b72d6Douglas Gregor        if (fence.get()) {
294561f81243f665cf2001caadc45df505f826b72d6Douglas Gregor            fenceFd = fence->dup();
295561f81243f665cf2001caadc45df505f826b72d6Douglas Gregor            if (fenceFd == -1) {
296561f81243f665cf2001caadc45df505f826b72d6Douglas Gregor                ALOGW("failed to dup layer fence, skipping sync: %d", errno);
297d0937224f383c7cc72c947119380f9713a070c73Douglas Gregor            }
298d0937224f383c7cc72c947119380f9713a070c73Douglas Gregor        }
299d0937224f383c7cc72c947119380f9713a070c73Douglas Gregor    }
300d0937224f383c7cc72c947119380f9713a070c73Douglas Gregor    layer.setAcquireFenceFd(fenceFd);
3017532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
3021734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregor
3031734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregorvoid Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
3041734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregor{
3051734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregor    ATRACE_CALL();
3061734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregor
3071734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregor    if (CC_UNLIKELY(mActiveBuffer == 0)) {
3081734317845d60307d474b5da8a8d33adbaf5e723Douglas Gregor        // the texture has not been created yet, this Layer has
3098cc488fefb2fb04bc8d5398da29f0182f97934cfChris Lattner        // in fact never been drawn into. This happens frequently with
310d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor        // SurfaceView because the WindowManager can't know when the client
3117532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // has drawn the first time.
312d538ed9b2a617239d5bd56357663de62f6f9224cAlexander Kornienko
313d538ed9b2a617239d5bd56357663de62f6f9224cAlexander Kornienko        // If there is nothing under us, we paint the screen in black, otherwise
314d538ed9b2a617239d5bd56357663de62f6f9224cAlexander Kornienko        // we just skip this update.
315de650ae96b53eb6109f29fdb5ee51c514259e6e4Douglas Gregor
316de650ae96b53eb6109f29fdb5ee51c514259e6e4Douglas Gregor        // figure out if there is something below us
3179bde77309fd2f9f7a53446e374472c48c81f5182Douglas Gregor        Region under;
318de650ae96b53eb6109f29fdb5ee51c514259e6e4Douglas Gregor        const SurfaceFlinger::LayerVector& drawingLayers(
3197532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                mFlinger->mDrawingState.layersSortedByZ);
3207532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        const size_t count = drawingLayers.size();
3217532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        for (size_t i=0 ; i<count ; ++i) {
3227532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            const sp<LayerBase>& layer(drawingLayers[i]);
3237532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            if (layer.get() == static_cast<LayerBase const*>(this))
3247532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                break;
3257532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
3267532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        }
3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        // if not everything below us is covered, we plug the holes!
3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        Region holes(clip.subtract(under));
3297532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        if (!holes.isEmpty()) {
3307532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            clearWithOpenGL(hw, holes, 0, 0, 0, 1);
3317532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        }
332db88d8ad74097e2601d81ee863ce46a8a48a7034Jeffrey Yasskin        return;
333db88d8ad74097e2601d81ee863ce46a8a48a7034Jeffrey Yasskin    }
334db88d8ad74097e2601d81ee863ce46a8a48a7034Jeffrey Yasskin
335db88d8ad74097e2601d81ee863ce46a8a48a7034Jeffrey Yasskin    // TODO: replace this with a server-side wait
336db88d8ad74097e2601d81ee863ce46a8a48a7034Jeffrey Yasskin    sp<Fence> fence = mSurfaceTexture->getCurrentFence();
337146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    if (fence.get()) {
338146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        status_t err = fence->wait(Fence::TIMEOUT_NEVER);
339146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
340146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        // Go ahead and draw the buffer anyway; no matter what we do the screen
341146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        // is probably going to have something visibly wrong.
342146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    }
343146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
344146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    if (!isProtected()) {
345146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        // TODO: we could be more subtle with isFixedSize()
346146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
347146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
348146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        // Query the texture matrix given our current filtering mode.
349146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        float textureMatrix[16];
350146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        mSurfaceTexture->setFilteringEnabled(useFiltering);
351146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        mSurfaceTexture->getTransformMatrix(textureMatrix);
352146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall
353146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        // Set things up for texturing.
354146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
355146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        GLenum filter = GL_NEAREST;
356146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        if (useFiltering) {
357146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall            filter = GL_LINEAR;
358146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        }
359146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
360146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
361146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glMatrixMode(GL_TEXTURE);
362146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glLoadMatrixf(textureMatrix);
363146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glMatrixMode(GL_MODELVIEW);
364146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glDisable(GL_TEXTURE_2D);
365146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glEnable(GL_TEXTURE_EXTERNAL_OES);
366146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall    } else {
367146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
368146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glMatrixMode(GL_TEXTURE);
369146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glLoadIdentity();
370146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glMatrixMode(GL_MODELVIEW);
371146060435c3efce95c95a092c7a1eb651cfb9ae0John McCall        glDisable(GL_TEXTURE_EXTERNAL_OES);
3727532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        glEnable(GL_TEXTURE_2D);
3737532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    }
3747532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
3757532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    drawWithOpenGL(hw, clip);
3767532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
3777532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    glDisable(GL_TEXTURE_EXTERNAL_OES);
3787532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    glDisable(GL_TEXTURE_2D);
3797532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
3807532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
381465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara// As documented in libhardware header, formats in the range
3827532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor// 0x100 - 0x1FF are specific to the HAL implementation, and
3837532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor// are known to have no alpha channel
3847532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor// TODO: move definition for device-specific range into
3857532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor// hardware.h, instead of using hard-coded values here.
3867532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
3877532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
3887532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorbool Layer::getOpacityForFormat(uint32_t format)
3897532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor{
3907532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    if (HARDWARE_IS_DEVICE_FORMAT(format)) {
3917532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        return true;
3927532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    }
393d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor    PixelFormatInfo info;
394d99cbe66403ee39c2ee58024b9582b95649a4fc5Douglas Gregor    status_t err = getPixelFormatInfo(PixelFormat(format), &info);
3950bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    // in case of error (unknown format), we assume no blending
3967532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    return (err || info.h_alpha <= info.l_alpha);
3977532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
3987532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
3997532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
4007532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorbool Layer::isOpaque() const
4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{
4020bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    // if we don't have a buffer yet, we're translucent regardless of the
4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // layer's opaque flag.
4047532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    if (mActiveBuffer == 0) {
4057532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        return false;
4067532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    }
4077532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
4087532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // if the layer has the opaque flag, then we're always opaque,
4097532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    // otherwise we use the current buffer's format.
4107532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    return mOpaqueLayer || mCurrentOpacity;
4117532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
4120bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall
4130bd6feb9e9d40fc889fd47e899985125a43dfed8John McCallbool Layer::isProtected() const
4140bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall{
4151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
4167532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    return (activeBuffer != 0) &&
4170bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall            (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
4180bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall}
4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4207532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregoruint32_t Layer::doTransaction(uint32_t flags)
4210bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall{
4227532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    ATRACE_CALL();
4237532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
4241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const Layer::State& front(drawingState());
4250bd6feb9e9d40fc889fd47e899985125a43dfed8John McCall    const Layer::State& temp(currentState());
4267532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
4277532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    const bool sizeChanged = (temp.requested.w != front.requested.w) ||
4287532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                             (temp.requested.h != front.requested.h);
4297532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
4307532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    if (sizeChanged) {
4317532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // the size changed, we need to ask our client to request a new buffer
4327532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        ALOGD_IF(DEBUG_RESIZE,
4337532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                "doTransaction: geometry (layer=%p), scalingMode=%d\n"
4347532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
4357532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
4363b6afbb99a1c44b4076f8e15fb7311405941b306Douglas Gregor                "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
4377532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
4387532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                this, mCurrentScalingMode,
4397532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.active.w, temp.active.h,
4407532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.active.crop.left,
4417532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.active.crop.top,
4427532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.active.crop.right,
443ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.active.crop.bottom,
444ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.active.crop.getWidth(),
445ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.active.crop.getHeight(),
446ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.requested.w, temp.requested.h,
447ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.requested.crop.left,
4487532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.requested.crop.top,
4497532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.requested.crop.right,
450ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.requested.crop.bottom,
451ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.requested.crop.getWidth(),
452ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                temp.requested.crop.getHeight(),
453ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.w, front.active.h,
454ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.crop.left,
455ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.crop.top,
456ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.crop.right,
457ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.crop.bottom,
458ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.crop.getWidth(),
459ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.active.crop.getHeight(),
460ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor                front.requested.w, front.requested.h,
4617532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                front.requested.crop.left,
4627532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                front.requested.crop.top,
4637532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                front.requested.crop.right,
4647532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                front.requested.crop.bottom,
4657532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                front.requested.crop.getWidth(),
4667532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                front.requested.crop.getHeight());
4677532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
4687532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // record the new size, form this point on, when the client request
4697532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // a buffer, it'll get the new size.
4707532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        mSurfaceTexture->setDefaultBufferSize(
4717532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                temp.requested.w, temp.requested.h);
4721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
473ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
474ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    if (!isFixedSize()) {
475ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
4767532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        const bool resizePending = (temp.requested.w != temp.active.w) ||
4771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                   (temp.requested.h != temp.active.h);
478ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
4797532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        if (resizePending) {
480ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            // don't let LayerBase::doTransaction update the drawing state
481ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            // if we have a pending resize, unless we are in fixed-size mode.
4827532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            // the drawing state will be updated only once we receive a buffer
483ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            // with the correct size.
484ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            //
485ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            // in particular, we want to make sure the clip (which is part
486ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            // of the geometry state) is latched together with the size but is
487ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            // latched immediately when no resizing is involved.
488ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
489ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor            flags |= eDontUpdateGeometryState;
490ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        }
491ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    }
492ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
493ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    return LayerBase::doTransaction(flags);
4947532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor}
4957532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
496ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregorbool Layer::isFixedSize() const {
4977532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
498ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor}
499ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
5007532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregorbool Layer::isCropped() const {
501ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    return !mCurrentCrop.isEmpty();
502ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor}
503ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
504ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor// ----------------------------------------------------------------------------
505ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor// pageflip handling...
506ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor// ----------------------------------------------------------------------------
507ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
508ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregorbool Layer::onPreComposition() {
509ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    mRefreshPending = false;
510ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    return mQueuedFrames > 0;
511ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor}
512ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
513ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregorvoid Layer::onPostComposition() {
514ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    if (mFrameLatencyNeeded) {
515ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        const HWComposer& hwc = mFlinger->getHwComposer();
516ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        const size_t offset = mFrameLatencyOffset;
517ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
5187532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        mFrameStats[offset].set = systemTime();
519ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        mFrameStats[offset].vsync = hwc.getRefreshTimestamp();
520ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
521ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        mFrameLatencyNeeded = false;
522ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    }
523ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor}
524ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
525ca1bdd7c269a2390d43c040a60511edd017ee130Douglas GregorRegion Layer::latchBuffer(bool& recomputeVisibleRegions)
526ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor{
527ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    ATRACE_CALL();
528ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor
529ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor    Region outDirtyRegion;
5307532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor    if (mQueuedFrames > 0) {
5317532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        // if we've already called updateTexImage() without going through
533ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        // a composition step, we have to skip this layer at this point
5347532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // because we cannot call updateTeximage() without a corresponding
535ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        // compositionComplete() call.
536ca1bdd7c269a2390d43c040a60511edd017ee130Douglas Gregor        // we'll trigger an update in onPreComposition().
5377532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        if (mRefreshPending) {
5387532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            return outDirtyRegion;
5397532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        }
540c960ee31c7e22a157a8cd31c92d9a9aa945e1e96Chris Lattner
5417532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // Capture the old state of the layer for comparisons later
5427532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        const bool oldOpacity = isOpaque();
5437532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
5447532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
5457532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        // signal another event if we have more frames pending
5467532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        if (android_atomic_dec(&mQueuedFrames) > 1) {
5477532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            mFlinger->signalLayerUpdate();
5487532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        }
5497532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
5507532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor        struct Reject : public SurfaceTexture::BufferRejecter {
5517532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            Layer::State& front;
5527532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            Layer::State& current;
5537532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            bool& recomputeVisibleRegions;
5547532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            Reject(Layer::State& front, Layer::State& current,
5557532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                    bool& recomputeVisibleRegions)
5567532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                : front(front), current(current),
5577532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                  recomputeVisibleRegions(recomputeVisibleRegions) {
5587532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor            }
5597532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor
560c960ee31c7e22a157a8cd31c92d9a9aa945e1e96Chris Lattner            virtual bool reject(const sp<GraphicBuffer>& buf,
5617532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                    const BufferQueue::BufferItem& item) {
5627532dc66648cfe7432c9fe66dec5225f0ab301c6Douglas Gregor                if (buf == NULL) {
563                    return false;
564                }
565
566                uint32_t bufWidth  = buf->getWidth();
567                uint32_t bufHeight = buf->getHeight();
568
569                // check that we received a buffer of the right size
570                // (Take the buffer's orientation into account)
571                if (item.mTransform & Transform::ROT_90) {
572                    swap(bufWidth, bufHeight);
573                }
574
575
576                bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
577                if (front.active != front.requested) {
578
579                    if (isFixedSize ||
580                            (bufWidth == front.requested.w &&
581                             bufHeight == front.requested.h))
582                    {
583                        // Here we pretend the transaction happened by updating the
584                        // current and drawing states. Drawing state is only accessed
585                        // in this thread, no need to have it locked
586                        front.active = front.requested;
587
588                        // We also need to update the current state so that
589                        // we don't end-up overwriting the drawing state with
590                        // this stale current state during the next transaction
591                        //
592                        // NOTE: We don't need to hold the transaction lock here
593                        // because State::active is only accessed from this thread.
594                        current.active = front.active;
595
596                        // recompute visible region
597                        recomputeVisibleRegions = true;
598                    }
599
600                    ALOGD_IF(DEBUG_RESIZE,
601                            "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
602                            "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
603                            "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
604                            this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
605                            front.active.w, front.active.h,
606                            front.active.crop.left,
607                            front.active.crop.top,
608                            front.active.crop.right,
609                            front.active.crop.bottom,
610                            front.active.crop.getWidth(),
611                            front.active.crop.getHeight(),
612                            front.requested.w, front.requested.h,
613                            front.requested.crop.left,
614                            front.requested.crop.top,
615                            front.requested.crop.right,
616                            front.requested.crop.bottom,
617                            front.requested.crop.getWidth(),
618                            front.requested.crop.getHeight());
619                }
620
621                if (!isFixedSize) {
622                    if (front.active.w != bufWidth ||
623                        front.active.h != bufHeight) {
624                        // reject this buffer
625                        return true;
626                    }
627                }
628                return false;
629            }
630        };
631
632
633        Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
634
635        // XXX: not sure if setTransformHint belongs here
636        // it should only be needed when the main screen orientation changes
637        mSurfaceTexture->setTransformHint(getTransformHint());
638
639        if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
640            // something happened!
641            recomputeVisibleRegions = true;
642            return outDirtyRegion;
643        }
644
645        // update the active buffer
646        mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
647        if (mActiveBuffer == NULL) {
648            // this can only happen if the very first buffer was rejected.
649            return outDirtyRegion;
650        }
651
652        mRefreshPending = true;
653        mFrameLatencyNeeded = true;
654        if (oldActiveBuffer == NULL) {
655             // the first time we receive a buffer, we need to trigger a
656             // geometry invalidation.
657             mFlinger->invalidateHwcGeometry();
658         }
659
660        Rect crop(mSurfaceTexture->getCurrentCrop());
661        const uint32_t transform(mSurfaceTexture->getCurrentTransform());
662        const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
663        if ((crop != mCurrentCrop) ||
664            (transform != mCurrentTransform) ||
665            (scalingMode != mCurrentScalingMode))
666        {
667            mCurrentCrop = crop;
668            mCurrentTransform = transform;
669            mCurrentScalingMode = scalingMode;
670            mFlinger->invalidateHwcGeometry();
671        }
672
673        if (oldActiveBuffer != NULL) {
674            uint32_t bufWidth  = mActiveBuffer->getWidth();
675            uint32_t bufHeight = mActiveBuffer->getHeight();
676            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
677                bufHeight != uint32_t(oldActiveBuffer->height)) {
678                mFlinger->invalidateHwcGeometry();
679            }
680        }
681
682        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
683        if (oldOpacity != isOpaque()) {
684            recomputeVisibleRegions = true;
685        }
686
687        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
688        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
689
690        // FIXME: postedRegion should be dirty & bounds
691        const Layer::State& front(drawingState());
692        Region dirtyRegion(Rect(front.active.w, front.active.h));
693
694        // transform the dirty region to window-manager space
695        outDirtyRegion = (front.transform.transform(dirtyRegion));
696    }
697    return outDirtyRegion;
698}
699
700void Layer::dump(String8& result, char* buffer, size_t SIZE) const
701{
702    LayerBaseClient::dump(result, buffer, SIZE);
703
704    sp<const GraphicBuffer> buf0(mActiveBuffer);
705    uint32_t w0=0, h0=0, s0=0, f0=0;
706    if (buf0 != 0) {
707        w0 = buf0->getWidth();
708        h0 = buf0->getHeight();
709        s0 = buf0->getStride();
710        f0 = buf0->format;
711    }
712    snprintf(buffer, SIZE,
713            "      "
714            "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
715            " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
716            mFormat, w0, h0, s0,f0,
717            getTransformHint(), mQueuedFrames, mRefreshPending);
718
719    result.append(buffer);
720
721    if (mSurfaceTexture != 0) {
722        mSurfaceTexture->dump(result, "            ", buffer, SIZE);
723    }
724}
725
726void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
727{
728    LayerBaseClient::dumpStats(result, buffer, SIZE);
729    const size_t o = mFrameLatencyOffset;
730    const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod();
731    result.appendFormat("%lld\n", period);
732    for (size_t i=0 ; i<128 ; i++) {
733        const size_t index = (o+i) % 128;
734        const nsecs_t time_app   = mFrameStats[index].timestamp;
735        const nsecs_t time_set   = mFrameStats[index].set;
736        const nsecs_t time_vsync = mFrameStats[index].vsync;
737        result.appendFormat("%lld\t%lld\t%lld\n",
738                time_app,
739                time_vsync,
740                time_set);
741    }
742    result.append("\n");
743}
744
745void Layer::clearStats()
746{
747    LayerBaseClient::clearStats();
748    memset(mFrameStats, 0, sizeof(mFrameStats));
749}
750
751uint32_t Layer::getEffectiveUsage(uint32_t usage) const
752{
753    // TODO: should we do something special if mSecure is set?
754    if (mProtectedByApp) {
755        // need a hardware-protected path to external video sink
756        usage |= GraphicBuffer::USAGE_PROTECTED;
757    }
758    usage |= GraphicBuffer::USAGE_HW_COMPOSER;
759    return usage;
760}
761
762uint32_t Layer::getTransformHint() const {
763    uint32_t orientation = 0;
764    if (!mFlinger->mDebugDisableTransformHint) {
765        // The transform hint is used to improve performance on the main
766        // display -- we can only have a single transform hint, it cannot
767        // apply to all displays.
768        // This is why we use the default display here. This is not an
769        // oversight.
770        sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
771        const Transform& planeTransform(hw->getTransform());
772        orientation = planeTransform.getOrientation();
773        if (orientation & Transform::ROT_INVALID) {
774            orientation = 0;
775        }
776    }
777    return orientation;
778}
779
780// ---------------------------------------------------------------------------
781
782
783}; // namespace android
784