Layer.cpp revision 789a6c3f1dfe22a1ffea7f39b2098d7842cd1f30
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2007 The Android Open Source Project 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * you may not use this file except in compliance with the License. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Unless required by applicable law or agreed to in writing, software 11558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS, 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the License for the specific language governing permissions and 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * limitations under the License. 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ATRACE_TAG ATRACE_TAG_GRAPHICS 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <stdlib.h> 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdint.h> 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <sys/types.h> 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <math.h> 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <cutils/compiler.h> 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <cutils/native_handle.h> 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <cutils/properties.h> 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <utils/Errors.h> 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <utils/Log.h> 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utils/StopWatch.h> 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utils/Trace.h> 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <ui/GraphicBuffer.h> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ui/PixelFormat.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gui/Surface.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clz.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "DisplayDevice.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GLExtensions.h" 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "Layer.h" 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "SurfaceFlinger.h" 43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "SurfaceTextureLayer.h" 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "DisplayHardware/HWComposer.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_RESIZE 0 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace android { 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// --------------------------------------------------------------------------- 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : LayerBaseClient(flinger, client), 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mTextureName(-1U), 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mQueuedFrames(0), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mCurrentTransform(0), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mCurrentOpacity(true), 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mRefreshPending(false), 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) mFrameLatencyNeeded(false), 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) mFormat(PIXEL_FORMAT_NONE), 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mGLExtensions(GLExtensions::getInstance()), 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mOpaqueLayer(true), 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mSecure(false), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mProtectedByApp(false) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mCurrentCrop.makeInvalid(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGenTextures(1, &mTextureName); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWComposer::HWCLayerInterface* layer) { 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LayerBaseClient::onLayerDisplayed(hw, layer); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (layer) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd()); 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid Layer::onFirstRef() 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LayerBaseClient::onFirstRef(); 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Creates a custom BufferQueue for SurfaceFlingerConsumer to use 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sp<BufferQueue> bq = new SurfaceTextureLayer(); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true, 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GL_TEXTURE_EXTERNAL_OES, false, bq); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mSurfaceFlingerConsumer->setFrameAvailableListener(this); 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) mSurfaceFlingerConsumer->setSynchronousMode(true); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#ifdef TARGET_DISABLE_TRIPLE_BUFFERING 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#warning "disabling triple buffering" 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) updateTransformHint(hw); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciLayer::~Layer() 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{ 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mFlinger->deleteTextureAsync(mTextureName); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Layer::onFrameAvailable() { 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) android_atomic_inc(&mQueuedFrames); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mFlinger->signalLayerUpdate(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// called with SurfaceFlinger::mStateLock as soon as the layer is entered 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the purgatory list 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Layer::onRemoved() 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mSurfaceFlingerConsumer->abandon(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Layer::setName(const String8& name) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LayerBase::setName(name); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mSurfaceFlingerConsumer->setName(name); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)sp<ISurface> Layer::createSurface() 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class provides an implementation of BnSurface (the "native" or 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "remote" side of the Binder IPC interface ISurface), and mixes in 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LayerCleaner to ensure that mFlinger->onLayerDestroyed() is called for 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this layer when the BSurface is destroyed. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The idea is to provide a handle to the Layer through ISurface that 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * is cleaned up automatically when the last reference to the ISurface 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * goes away. (The references will be held on the "proxy" side, while 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Layer exists on the "native" side.) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * The Layer has a reference to an instance of SurfaceFlinger's variant 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * of GLConsumer, which holds a reference to the BufferQueue. The 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * getSurfaceTexture() call returns a Binder interface reference for 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the producer interface of the buffer queue associated with the Layer. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class BSurface : public BnSurface, public LayerCleaner { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wp<const Layer> mOwner; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sp<IGraphicBufferProducer> res; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sp<const Layer> that( mOwner.promote() ); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (that != NULL) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) res = that->mSurfaceFlingerConsumer->getBufferQueue(); 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return res; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSurface(const sp<SurfaceFlinger>& flinger, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sp<Layer>& layer) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : LayerCleaner(flinger, layer), mOwner(layer) { } 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sp<ISurface> sur(new BSurface(mFlinger, this)); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sur; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)wp<IBinder> Layer::getSurfaceTextureBinder() const 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{ 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return mSurfaceFlingerConsumer->getBufferQueue()->asBinder(); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)status_t Layer::setBuffers( uint32_t w, uint32_t h, 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PixelFormat format, uint32_t flags) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // this surfaces pixel format 172558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch PixelFormatInfo info; 173558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch status_t err = getPixelFormatInfo(format, &info); 174558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (err) { 175558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ALOGE("unsupported pixelformat %d", format); 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return err; 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32_t const maxSurfaceDims = min( 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // never allow a surface larger than what our underlying GL implementation 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // can handle. 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return BAD_VALUE; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) mFormat = format; 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mCurrentOpacity = getOpacityForFormat(format); 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mSurfaceFlingerConsumer->setDefaultBufferFormat(format); 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return NO_ERROR; 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciRect Layer::computeBufferCrop() const { 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Start with the SurfaceFlingerConsumer's buffer crop... 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Rect crop; 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!mCurrentCrop.isEmpty()) { 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crop = mCurrentCrop; 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (mActiveBuffer != NULL){ 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crop.makeInvalid(); 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return crop; 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ... then reduce that in the same proportions as the window crop reduces 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the window size. 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const State& s(drawingState()); 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!s.active.crop.isEmpty()) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transform the window crop to match the buffer coordinate system, 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // which means using the inverse of the current transform set on the 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // SurfaceFlingerConsumer. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t invTransform = mCurrentTransform; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int winWidth = s.active.w; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int winHeight = s.active.h; 225 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 226 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | 227 NATIVE_WINDOW_TRANSFORM_FLIP_H; 228 winWidth = s.active.h; 229 winHeight = s.active.w; 230 } 231 Rect winCrop = s.active.crop.transform(invTransform, 232 s.active.w, s.active.h); 233 234 float xScale = float(crop.width()) / float(winWidth); 235 float yScale = float(crop.height()) / float(winHeight); 236 crop.left += int(ceilf(float(winCrop.left) * xScale)); 237 crop.top += int(ceilf(float(winCrop.top) * yScale)); 238 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale)); 239 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale)); 240 } 241 242 return crop; 243} 244 245void Layer::setGeometry( 246 const sp<const DisplayDevice>& hw, 247 HWComposer::HWCLayerInterface& layer) 248{ 249 LayerBaseClient::setGeometry(hw, layer); 250 251 // enable this layer 252 layer.setSkip(false); 253 254 if (isSecure() && !hw->isSecure()) { 255 layer.setSkip(true); 256 } 257 258 const State& s(drawingState()); 259 layer.setPlaneAlpha(s.alpha); 260 261 /* 262 * Transformations are applied in this order: 263 * 1) buffer orientation/flip/mirror 264 * 2) state transformation (window manager) 265 * 3) layer orientation (screen orientation) 266 * (NOTE: the matrices are multiplied in reverse order) 267 */ 268 269 const Transform bufferOrientation(mCurrentTransform); 270 const Transform tr(hw->getTransform() * s.transform * bufferOrientation); 271 272 // this gives us only the "orientation" component of the transform 273 const uint32_t finalTransform = tr.getOrientation(); 274 275 // we can only handle simple transformation 276 if (finalTransform & Transform::ROT_INVALID) { 277 layer.setSkip(true); 278 } else { 279 layer.setTransform(finalTransform); 280 } 281 layer.setCrop(computeBufferCrop()); 282} 283 284void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, 285 HWComposer::HWCLayerInterface& layer) { 286 LayerBaseClient::setPerFrameData(hw, layer); 287 // NOTE: buffer can be NULL if the client never drew into this 288 // layer yet, or if we ran out of memory 289 layer.setBuffer(mActiveBuffer); 290} 291 292void Layer::setAcquireFence(const sp<const DisplayDevice>& hw, 293 HWComposer::HWCLayerInterface& layer) { 294 int fenceFd = -1; 295 296 // TODO: there is a possible optimization here: we only need to set the 297 // acquire fence the first time a new buffer is acquired on EACH display. 298 299 if (layer.getCompositionType() == HWC_OVERLAY) { 300 sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence(); 301 if (fence->isValid()) { 302 fenceFd = fence->dup(); 303 if (fenceFd == -1) { 304 ALOGW("failed to dup layer fence, skipping sync: %d", errno); 305 } 306 } 307 } 308 layer.setAcquireFenceFd(fenceFd); 309} 310 311void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const 312{ 313 ATRACE_CALL(); 314 315 if (CC_UNLIKELY(mActiveBuffer == 0)) { 316 // the texture has not been created yet, this Layer has 317 // in fact never been drawn into. This happens frequently with 318 // SurfaceView because the WindowManager can't know when the client 319 // has drawn the first time. 320 321 // If there is nothing under us, we paint the screen in black, otherwise 322 // we just skip this update. 323 324 // figure out if there is something below us 325 Region under; 326 const SurfaceFlinger::LayerVector& drawingLayers( 327 mFlinger->mDrawingState.layersSortedByZ); 328 const size_t count = drawingLayers.size(); 329 for (size_t i=0 ; i<count ; ++i) { 330 const sp<LayerBase>& layer(drawingLayers[i]); 331 if (layer.get() == static_cast<LayerBase const*>(this)) 332 break; 333 under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); 334 } 335 // if not everything below us is covered, we plug the holes! 336 Region holes(clip.subtract(under)); 337 if (!holes.isEmpty()) { 338 clearWithOpenGL(hw, holes, 0, 0, 0, 1); 339 } 340 return; 341 } 342 343 // Bind the current buffer to the GL texture, and wait for it to be 344 // ready for us to draw into. 345 status_t err = mSurfaceFlingerConsumer->bindTextureImage(); 346 if (err != NO_ERROR) { 347 ALOGW("onDraw: bindTextureImage failed (err=%d)", err); 348 // Go ahead and draw the buffer anyway; no matter what we do the screen 349 // is probably going to have something visibly wrong. 350 } 351 352 bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); 353 354 if (!blackOutLayer) { 355 // TODO: we could be more subtle with isFixedSize() 356 const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); 357 358 // Query the texture matrix given our current filtering mode. 359 float textureMatrix[16]; 360 mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); 361 mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); 362 363 // Set things up for texturing. 364 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName); 365 GLenum filter = GL_NEAREST; 366 if (useFiltering) { 367 filter = GL_LINEAR; 368 } 369 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter); 370 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter); 371 glMatrixMode(GL_TEXTURE); 372 glLoadMatrixf(textureMatrix); 373 glMatrixMode(GL_MODELVIEW); 374 glDisable(GL_TEXTURE_2D); 375 glEnable(GL_TEXTURE_EXTERNAL_OES); 376 } else { 377 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName()); 378 glMatrixMode(GL_TEXTURE); 379 glLoadIdentity(); 380 glMatrixMode(GL_MODELVIEW); 381 glDisable(GL_TEXTURE_EXTERNAL_OES); 382 glEnable(GL_TEXTURE_2D); 383 } 384 385 drawWithOpenGL(hw, clip); 386 387 glDisable(GL_TEXTURE_EXTERNAL_OES); 388 glDisable(GL_TEXTURE_2D); 389} 390 391// As documented in libhardware header, formats in the range 392// 0x100 - 0x1FF are specific to the HAL implementation, and 393// are known to have no alpha channel 394// TODO: move definition for device-specific range into 395// hardware.h, instead of using hard-coded values here. 396#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) 397 398bool Layer::getOpacityForFormat(uint32_t format) 399{ 400 if (HARDWARE_IS_DEVICE_FORMAT(format)) { 401 return true; 402 } 403 PixelFormatInfo info; 404 status_t err = getPixelFormatInfo(PixelFormat(format), &info); 405 // in case of error (unknown format), we assume no blending 406 return (err || info.h_alpha <= info.l_alpha); 407} 408 409 410bool Layer::isOpaque() const 411{ 412 // if we don't have a buffer yet, we're translucent regardless of the 413 // layer's opaque flag. 414 if (mActiveBuffer == 0) { 415 return false; 416 } 417 418 // if the layer has the opaque flag, then we're always opaque, 419 // otherwise we use the current buffer's format. 420 return mOpaqueLayer || mCurrentOpacity; 421} 422 423bool Layer::isProtected() const 424{ 425 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); 426 return (activeBuffer != 0) && 427 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); 428} 429 430uint32_t Layer::doTransaction(uint32_t flags) 431{ 432 ATRACE_CALL(); 433 434 const Layer::State& front(drawingState()); 435 const Layer::State& temp(currentState()); 436 437 const bool sizeChanged = (temp.requested.w != front.requested.w) || 438 (temp.requested.h != front.requested.h); 439 440 if (sizeChanged) { 441 // the size changed, we need to ask our client to request a new buffer 442 ALOGD_IF(DEBUG_RESIZE, 443 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" 444 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" 445 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n" 446 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" 447 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n", 448 this, (const char*) getName(), mCurrentTransform, mCurrentScalingMode, 449 temp.active.w, temp.active.h, 450 temp.active.crop.left, 451 temp.active.crop.top, 452 temp.active.crop.right, 453 temp.active.crop.bottom, 454 temp.active.crop.getWidth(), 455 temp.active.crop.getHeight(), 456 temp.requested.w, temp.requested.h, 457 temp.requested.crop.left, 458 temp.requested.crop.top, 459 temp.requested.crop.right, 460 temp.requested.crop.bottom, 461 temp.requested.crop.getWidth(), 462 temp.requested.crop.getHeight(), 463 front.active.w, front.active.h, 464 front.active.crop.left, 465 front.active.crop.top, 466 front.active.crop.right, 467 front.active.crop.bottom, 468 front.active.crop.getWidth(), 469 front.active.crop.getHeight(), 470 front.requested.w, front.requested.h, 471 front.requested.crop.left, 472 front.requested.crop.top, 473 front.requested.crop.right, 474 front.requested.crop.bottom, 475 front.requested.crop.getWidth(), 476 front.requested.crop.getHeight()); 477 478 // record the new size, form this point on, when the client request 479 // a buffer, it'll get the new size. 480 mSurfaceFlingerConsumer->setDefaultBufferSize( 481 temp.requested.w, temp.requested.h); 482 } 483 484 if (!isFixedSize()) { 485 486 const bool resizePending = (temp.requested.w != temp.active.w) || 487 (temp.requested.h != temp.active.h); 488 489 if (resizePending) { 490 // don't let LayerBase::doTransaction update the drawing state 491 // if we have a pending resize, unless we are in fixed-size mode. 492 // the drawing state will be updated only once we receive a buffer 493 // with the correct size. 494 // 495 // in particular, we want to make sure the clip (which is part 496 // of the geometry state) is latched together with the size but is 497 // latched immediately when no resizing is involved. 498 499 flags |= eDontUpdateGeometryState; 500 } 501 } 502 503 return LayerBase::doTransaction(flags); 504} 505 506bool Layer::isFixedSize() const { 507 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; 508} 509 510bool Layer::isCropped() const { 511 return !mCurrentCrop.isEmpty(); 512} 513 514// ---------------------------------------------------------------------------- 515// pageflip handling... 516// ---------------------------------------------------------------------------- 517 518bool Layer::onPreComposition() { 519 mRefreshPending = false; 520 return mQueuedFrames > 0; 521} 522 523void Layer::onPostComposition() { 524 if (mFrameLatencyNeeded) { 525 nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); 526 mFrameTracker.setDesiredPresentTime(desiredPresentTime); 527 528 sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence(); 529 if (frameReadyFence->isValid()) { 530 mFrameTracker.setFrameReadyFence(frameReadyFence); 531 } else { 532 // There was no fence for this frame, so assume that it was ready 533 // to be presented at the desired present time. 534 mFrameTracker.setFrameReadyTime(desiredPresentTime); 535 } 536 537 const HWComposer& hwc = mFlinger->getHwComposer(); 538 sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); 539 if (presentFence->isValid()) { 540 mFrameTracker.setActualPresentFence(presentFence); 541 } else { 542 // The HWC doesn't support present fences, so use the refresh 543 // timestamp instead. 544 nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); 545 mFrameTracker.setActualPresentTime(presentTime); 546 } 547 548 mFrameTracker.advanceFrame(); 549 mFrameLatencyNeeded = false; 550 } 551} 552 553bool Layer::isVisible() const { 554 return LayerBaseClient::isVisible() && (mActiveBuffer != NULL); 555} 556 557Region Layer::latchBuffer(bool& recomputeVisibleRegions) 558{ 559 ATRACE_CALL(); 560 561 Region outDirtyRegion; 562 if (mQueuedFrames > 0) { 563 564 // if we've already called updateTexImage() without going through 565 // a composition step, we have to skip this layer at this point 566 // because we cannot call updateTeximage() without a corresponding 567 // compositionComplete() call. 568 // we'll trigger an update in onPreComposition(). 569 if (mRefreshPending) { 570 return outDirtyRegion; 571 } 572 573 // Capture the old state of the layer for comparisons later 574 const bool oldOpacity = isOpaque(); 575 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; 576 577 // signal another event if we have more frames pending 578 if (android_atomic_dec(&mQueuedFrames) > 1) { 579 mFlinger->signalLayerUpdate(); 580 } 581 582 struct Reject : public SurfaceFlingerConsumer::BufferRejecter { 583 Layer::State& front; 584 Layer::State& current; 585 bool& recomputeVisibleRegions; 586 Reject(Layer::State& front, Layer::State& current, 587 bool& recomputeVisibleRegions) 588 : front(front), current(current), 589 recomputeVisibleRegions(recomputeVisibleRegions) { 590 } 591 592 virtual bool reject(const sp<GraphicBuffer>& buf, 593 const BufferQueue::BufferItem& item) { 594 if (buf == NULL) { 595 return false; 596 } 597 598 uint32_t bufWidth = buf->getWidth(); 599 uint32_t bufHeight = buf->getHeight(); 600 601 // check that we received a buffer of the right size 602 // (Take the buffer's orientation into account) 603 if (item.mTransform & Transform::ROT_90) { 604 swap(bufWidth, bufHeight); 605 } 606 607 608 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; 609 if (front.active != front.requested) { 610 611 if (isFixedSize || 612 (bufWidth == front.requested.w && 613 bufHeight == front.requested.h)) 614 { 615 // Here we pretend the transaction happened by updating the 616 // current and drawing states. Drawing state is only accessed 617 // in this thread, no need to have it locked 618 front.active = front.requested; 619 620 // We also need to update the current state so that 621 // we don't end-up overwriting the drawing state with 622 // this stale current state during the next transaction 623 // 624 // NOTE: We don't need to hold the transaction lock here 625 // because State::active is only accessed from this thread. 626 current.active = front.active; 627 628 // recompute visible region 629 recomputeVisibleRegions = true; 630 } 631 632 ALOGD_IF(DEBUG_RESIZE, 633 "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" 634 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" 635 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n", 636 bufWidth, bufHeight, item.mTransform, item.mScalingMode, 637 front.active.w, front.active.h, 638 front.active.crop.left, 639 front.active.crop.top, 640 front.active.crop.right, 641 front.active.crop.bottom, 642 front.active.crop.getWidth(), 643 front.active.crop.getHeight(), 644 front.requested.w, front.requested.h, 645 front.requested.crop.left, 646 front.requested.crop.top, 647 front.requested.crop.right, 648 front.requested.crop.bottom, 649 front.requested.crop.getWidth(), 650 front.requested.crop.getHeight()); 651 } 652 653 if (!isFixedSize) { 654 if (front.active.w != bufWidth || 655 front.active.h != bufHeight) { 656 // reject this buffer 657 return true; 658 } 659 } 660 return false; 661 } 662 }; 663 664 665 Reject r(mDrawingState, currentState(), recomputeVisibleRegions); 666 667 if (mSurfaceFlingerConsumer->updateTexImage(&r) != NO_ERROR) { 668 // something happened! 669 recomputeVisibleRegions = true; 670 return outDirtyRegion; 671 } 672 673 // update the active buffer 674 mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(); 675 if (mActiveBuffer == NULL) { 676 // this can only happen if the very first buffer was rejected. 677 return outDirtyRegion; 678 } 679 680 mRefreshPending = true; 681 mFrameLatencyNeeded = true; 682 if (oldActiveBuffer == NULL) { 683 // the first time we receive a buffer, we need to trigger a 684 // geometry invalidation. 685 recomputeVisibleRegions = true; 686 } 687 688 Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); 689 const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); 690 const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); 691 if ((crop != mCurrentCrop) || 692 (transform != mCurrentTransform) || 693 (scalingMode != mCurrentScalingMode)) 694 { 695 mCurrentCrop = crop; 696 mCurrentTransform = transform; 697 mCurrentScalingMode = scalingMode; 698 recomputeVisibleRegions = true; 699 } 700 701 if (oldActiveBuffer != NULL) { 702 uint32_t bufWidth = mActiveBuffer->getWidth(); 703 uint32_t bufHeight = mActiveBuffer->getHeight(); 704 if (bufWidth != uint32_t(oldActiveBuffer->width) || 705 bufHeight != uint32_t(oldActiveBuffer->height)) { 706 recomputeVisibleRegions = true; 707 } 708 } 709 710 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); 711 if (oldOpacity != isOpaque()) { 712 recomputeVisibleRegions = true; 713 } 714 715 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 716 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 717 718 // FIXME: postedRegion should be dirty & bounds 719 const Layer::State& front(drawingState()); 720 Region dirtyRegion(Rect(front.active.w, front.active.h)); 721 722 // transform the dirty region to window-manager space 723 outDirtyRegion = (front.transform.transform(dirtyRegion)); 724 } 725 return outDirtyRegion; 726} 727 728void Layer::dump(String8& result, char* buffer, size_t SIZE) const 729{ 730 LayerBaseClient::dump(result, buffer, SIZE); 731 732 sp<const GraphicBuffer> buf0(mActiveBuffer); 733 uint32_t w0=0, h0=0, s0=0, f0=0; 734 if (buf0 != 0) { 735 w0 = buf0->getWidth(); 736 h0 = buf0->getHeight(); 737 s0 = buf0->getStride(); 738 f0 = buf0->format; 739 } 740 snprintf(buffer, SIZE, 741 " " 742 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X]," 743 " queued-frames=%d, mRefreshPending=%d\n", 744 mFormat, w0, h0, s0,f0, 745 mQueuedFrames, mRefreshPending); 746 747 result.append(buffer); 748 749 if (mSurfaceFlingerConsumer != 0) { 750 mSurfaceFlingerConsumer->dump(result, " ", buffer, SIZE); 751 } 752} 753 754void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const 755{ 756 LayerBaseClient::dumpStats(result, buffer, SIZE); 757 mFrameTracker.dump(result); 758} 759 760void Layer::clearStats() 761{ 762 LayerBaseClient::clearStats(); 763 mFrameTracker.clear(); 764} 765 766uint32_t Layer::getEffectiveUsage(uint32_t usage) const 767{ 768 // TODO: should we do something special if mSecure is set? 769 if (mProtectedByApp) { 770 // need a hardware-protected path to external video sink 771 usage |= GraphicBuffer::USAGE_PROTECTED; 772 } 773 usage |= GraphicBuffer::USAGE_HW_COMPOSER; 774 return usage; 775} 776 777void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { 778 uint32_t orientation = 0; 779 if (!mFlinger->mDebugDisableTransformHint) { 780 // The transform hint is used to improve performance, but we can 781 // only have a single transform hint, it cannot 782 // apply to all displays. 783 const Transform& planeTransform(hw->getTransform()); 784 orientation = planeTransform.getOrientation(); 785 if (orientation & Transform::ROT_INVALID) { 786 orientation = 0; 787 } 788 } 789 mSurfaceFlingerConsumer->setTransformHint(orientation); 790} 791 792// --------------------------------------------------------------------------- 793 794 795}; // namespace android 796