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