| 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> | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 30 | #include <utils/NativeHandle.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 31 | #include <utils/StopWatch.h> | 
| Jamie Gennis | 1c8e95c | 2012-02-23 19:27:23 -0800 | [diff] [blame] | 32 | #include <utils/Trace.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 33 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 34 | #include <ui/GraphicBuffer.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 35 | #include <ui/PixelFormat.h> | 
| Mathias Agopian | 9cce325 | 2010-02-09 17:46:37 -0800 | [diff] [blame] | 36 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 37 | #include <gui/BufferItem.h> | 
| Mathias Agopian | 90ac799 | 2012-02-25 18:48:35 -0800 | [diff] [blame] | 38 | #include <gui/Surface.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 39 |  | 
 | 40 | #include "clz.h" | 
| Mathias Agopian | 3e25fd8 | 2013-04-22 17:52:16 +0200 | [diff] [blame] | 41 | #include "Colorizer.h" | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 42 | #include "DisplayDevice.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 43 | #include "Layer.h" | 
| Dan Stoza | b9b0883 | 2014-03-13 11:55:57 -0700 | [diff] [blame] | 44 | #include "MonitoredProducer.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 45 | #include "SurfaceFlinger.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 46 |  | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 47 | #include "DisplayHardware/HWComposer.h" | 
 | 48 |  | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 49 | #include "RenderEngine/RenderEngine.h" | 
 | 50 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 51 | #define DEBUG_RESIZE    0 | 
 | 52 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 53 | namespace android { | 
 | 54 |  | 
 | 55 | // --------------------------------------------------------------------------- | 
 | 56 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 57 | int32_t Layer::sSequence = 1; | 
 | 58 |  | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 59 | Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, | 
 | 60 |         const String8& name, uint32_t w, uint32_t h, uint32_t flags) | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 61 |     :   contentDirty(false), | 
 | 62 |         sequence(uint32_t(android_atomic_inc(&sSequence))), | 
 | 63 |         mFlinger(flinger), | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 64 |         mTextureName(-1U), | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 65 |         mPremultipliedAlpha(true), | 
 | 66 |         mName("unnamed"), | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 67 |         mFormat(PIXEL_FORMAT_NONE), | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 68 |         mTransactionFlags(0), | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 69 |         mQueuedFrames(0), | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 70 |         mSidebandStreamChanged(false), | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 71 |         mCurrentTransform(0), | 
| Mathias Agopian | 933389f | 2011-07-18 16:15:08 -0700 | [diff] [blame] | 72 |         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 73 |         mCurrentOpacity(true), | 
| Mathias Agopian | 4d143ee | 2012-02-23 20:05:39 -0800 | [diff] [blame] | 74 |         mRefreshPending(false), | 
| Mathias Agopian | 82d7ab6 | 2012-01-19 18:34:40 -0800 | [diff] [blame] | 75 |         mFrameLatencyNeeded(false), | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 76 |         mFiltering(false), | 
 | 77 |         mNeedsFiltering(false), | 
| Mathias Agopian | 5cdc899 | 2013-08-13 20:51:23 -0700 | [diff] [blame] | 78 |         mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2), | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 79 |         mProtectedByApp(false), | 
 | 80 |         mHasSurface(false), | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 81 |         mClientRef(client), | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 82 |         mPotentialCursor(false), | 
 | 83 |         mQueueItemLock(), | 
 | 84 |         mQueueItemCondition(), | 
 | 85 |         mQueueItems(), | 
| Dan Stoza | 65476f3 | 2015-05-14 09:27:25 -0700 | [diff] [blame] | 86 |         mLastFrameNumberReceived(0), | 
 | 87 |         mUpdateTexImageFailed(false) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 88 | { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 89 |     mCurrentCrop.makeInvalid(); | 
| Mathias Agopian | 3f84483 | 2013-08-07 21:24:32 -0700 | [diff] [blame] | 90 |     mFlinger->getRenderEngine().genTextures(1, &mTextureName); | 
| Mathias Agopian | 49457ac | 2013-08-14 18:20:17 -0700 | [diff] [blame] | 91 |     mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 92 |  | 
 | 93 |     uint32_t layerFlags = 0; | 
 | 94 |     if (flags & ISurfaceComposerClient::eHidden) | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 95 |         layerFlags |= layer_state_t::eLayerHidden; | 
 | 96 |     if (flags & ISurfaceComposerClient::eOpaque) | 
 | 97 |         layerFlags |= layer_state_t::eLayerOpaque; | 
| Dan Stoza | 2311608 | 2015-06-18 14:58:39 -0700 | [diff] [blame] | 98 |     if (flags & ISurfaceComposerClient::eSecure) | 
 | 99 |         layerFlags |= layer_state_t::eLayerSecure; | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 100 |  | 
 | 101 |     if (flags & ISurfaceComposerClient::eNonPremultiplied) | 
 | 102 |         mPremultipliedAlpha = false; | 
 | 103 |  | 
 | 104 |     mName = name; | 
 | 105 |  | 
 | 106 |     mCurrentState.active.w = w; | 
 | 107 |     mCurrentState.active.h = h; | 
 | 108 |     mCurrentState.active.crop.makeInvalid(); | 
 | 109 |     mCurrentState.z = 0; | 
 | 110 |     mCurrentState.alpha = 0xFF; | 
 | 111 |     mCurrentState.layerStack = 0; | 
 | 112 |     mCurrentState.flags = layerFlags; | 
 | 113 |     mCurrentState.sequence = 0; | 
 | 114 |     mCurrentState.transform.set(0, 0); | 
 | 115 |     mCurrentState.requested = mCurrentState.active; | 
 | 116 |  | 
 | 117 |     // drawing state & current state are identical | 
 | 118 |     mDrawingState = mCurrentState; | 
| Jamie Gennis | 6547ff4 | 2013-07-16 20:12:42 -0700 | [diff] [blame] | 119 |  | 
 | 120 |     nsecs_t displayPeriod = | 
 | 121 |             flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); | 
 | 122 |     mFrameTracker.setDisplayRefreshPeriod(displayPeriod); | 
| Jamie Gennis | e8696a4 | 2012-01-15 18:54:57 -0800 | [diff] [blame] | 123 | } | 
 | 124 |  | 
| Mathias Agopian | 3f84483 | 2013-08-07 21:24:32 -0700 | [diff] [blame] | 125 | void Layer::onFirstRef() { | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 126 |     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use | 
| Dan Stoza | b3d0bdf | 2014-04-07 16:33:59 -0700 | [diff] [blame] | 127 |     sp<IGraphicBufferProducer> producer; | 
 | 128 |     sp<IGraphicBufferConsumer> consumer; | 
| Dan Stoza | b9b0883 | 2014-03-13 11:55:57 -0700 | [diff] [blame] | 129 |     BufferQueue::createBufferQueue(&producer, &consumer); | 
 | 130 |     mProducer = new MonitoredProducer(producer, mFlinger); | 
 | 131 |     mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName); | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 132 |     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 133 |     mSurfaceFlingerConsumer->setContentsChangedListener(this); | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 134 |     mSurfaceFlingerConsumer->setName(mName); | 
| Daniel Lam | b267579 | 2012-02-23 14:35:13 -0800 | [diff] [blame] | 135 |  | 
| Mathias Agopian | 7f42a9c | 2012-04-23 20:00:16 -0700 | [diff] [blame] | 136 | #ifdef TARGET_DISABLE_TRIPLE_BUFFERING | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 137 |     mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); | 
| Mathias Agopian | 7f42a9c | 2012-04-23 20:00:16 -0700 | [diff] [blame] | 138 | #else | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 139 |     mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); | 
| Mathias Agopian | 303d538 | 2012-02-05 01:49:16 -0800 | [diff] [blame] | 140 | #endif | 
| Andy McFadden | 6905205 | 2012-09-14 16:10:11 -0700 | [diff] [blame] | 141 |  | 
| Mathias Agopian | 8430095 | 2012-11-21 16:02:13 -0800 | [diff] [blame] | 142 |     const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); | 
 | 143 |     updateTransformHint(hw); | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 144 | } | 
 | 145 |  | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 146 | Layer::~Layer() { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 147 |     sp<Client> c(mClientRef.promote()); | 
 | 148 |     if (c != 0) { | 
 | 149 |         c->detachLayer(this); | 
 | 150 |     } | 
| Mathias Agopian | 921e6ac | 2012-07-23 23:11:29 -0700 | [diff] [blame] | 151 |     mFlinger->deleteTextureAsync(mTextureName); | 
| Jamie Gennis | 6547ff4 | 2013-07-16 20:12:42 -0700 | [diff] [blame] | 152 |     mFrameTracker.logAndResetStats(mName); | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 153 | } | 
 | 154 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 155 | // --------------------------------------------------------------------------- | 
 | 156 | // callbacks | 
 | 157 | // --------------------------------------------------------------------------- | 
 | 158 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 159 | void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 160 |         HWComposer::HWCLayerInterface* layer) { | 
 | 161 |     if (layer) { | 
 | 162 |         layer->onDisplayed(); | 
| Jesse Hall | 13f01cb | 2013-03-20 11:37:21 -0700 | [diff] [blame] | 163 |         mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 164 |     } | 
 | 165 | } | 
 | 166 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 167 | void Layer::onFrameAvailable(const BufferItem& item) { | 
 | 168 |     // Add this buffer from our internal queue tracker | 
 | 169 |     { // Autolock scope | 
 | 170 |         Mutex::Autolock lock(mQueueItemLock); | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 171 |  | 
 | 172 |         // Reset the frame number tracker when we receive the first buffer after | 
 | 173 |         // a frame number reset | 
 | 174 |         if (item.mFrameNumber == 1) { | 
 | 175 |             mLastFrameNumberReceived = 0; | 
 | 176 |         } | 
 | 177 |  | 
 | 178 |         // Ensure that callbacks are handled in order | 
 | 179 |         while (item.mFrameNumber != mLastFrameNumberReceived + 1) { | 
 | 180 |             status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, | 
 | 181 |                     ms2ns(500)); | 
 | 182 |             if (result != NO_ERROR) { | 
 | 183 |                 ALOGE("[%s] Timed out waiting on callback", mName.string()); | 
 | 184 |             } | 
 | 185 |         } | 
 | 186 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 187 |         mQueueItems.push_back(item); | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 188 |         android_atomic_inc(&mQueuedFrames); | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 189 |  | 
 | 190 |         // Wake up any pending callbacks | 
 | 191 |         mLastFrameNumberReceived = item.mFrameNumber; | 
 | 192 |         mQueueItemCondition.broadcast(); | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 193 |     } | 
 | 194 |  | 
| Mathias Agopian | 99ce5cd | 2012-01-31 18:24:27 -0800 | [diff] [blame] | 195 |     mFlinger->signalLayerUpdate(); | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 196 | } | 
 | 197 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 198 | void Layer::onFrameReplaced(const BufferItem& item) { | 
 | 199 |     Mutex::Autolock lock(mQueueItemLock); | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 200 |  | 
 | 201 |     // Ensure that callbacks are handled in order | 
 | 202 |     while (item.mFrameNumber != mLastFrameNumberReceived + 1) { | 
 | 203 |         status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, | 
 | 204 |                 ms2ns(500)); | 
 | 205 |         if (result != NO_ERROR) { | 
 | 206 |             ALOGE("[%s] Timed out waiting on callback", mName.string()); | 
 | 207 |         } | 
 | 208 |     } | 
 | 209 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 210 |     if (mQueueItems.empty()) { | 
 | 211 |         ALOGE("Can't replace a frame on an empty queue"); | 
 | 212 |         return; | 
 | 213 |     } | 
 | 214 |     mQueueItems.editItemAt(0) = item; | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 215 |  | 
 | 216 |     // Wake up any pending callbacks | 
 | 217 |     mLastFrameNumberReceived = item.mFrameNumber; | 
 | 218 |     mQueueItemCondition.broadcast(); | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 219 | } | 
 | 220 |  | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 221 | void Layer::onSidebandStreamChanged() { | 
 | 222 |     if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { | 
 | 223 |         // mSidebandStreamChanged was false | 
 | 224 |         mFlinger->signalLayerUpdate(); | 
 | 225 |     } | 
 | 226 | } | 
 | 227 |  | 
| Mathias Agopian | 6710604 | 2013-03-14 19:18:13 -0700 | [diff] [blame] | 228 | // called with SurfaceFlinger::mStateLock from the drawing thread after | 
 | 229 | // the layer has been remove from the current state list (and just before | 
 | 230 | // it's removed from the drawing state list) | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 231 | void Layer::onRemoved() { | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 232 |     mSurfaceFlingerConsumer->abandon(); | 
| Mathias Agopian | 48d819a | 2009-09-10 19:41:18 -0700 | [diff] [blame] | 233 | } | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 234 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 235 | // --------------------------------------------------------------------------- | 
 | 236 | // set-up | 
 | 237 | // --------------------------------------------------------------------------- | 
 | 238 |  | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 239 | const String8& Layer::getName() const { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 240 |     return mName; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 241 | } | 
 | 242 |  | 
| Mathias Agopian | f9d9327 | 2009-06-19 17:00:27 -0700 | [diff] [blame] | 243 | 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] | 244 |                             PixelFormat format, uint32_t flags) | 
 | 245 | { | 
| Mathias Agopian | ca99fb8 | 2010-04-14 16:43:44 -0700 | [diff] [blame] | 246 |     uint32_t const maxSurfaceDims = min( | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 247 |             mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); | 
| Mathias Agopian | ca99fb8 | 2010-04-14 16:43:44 -0700 | [diff] [blame] | 248 |  | 
 | 249 |     // never allow a surface larger than what our underlying GL implementation | 
 | 250 |     // can handle. | 
 | 251 |     if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { | 
| Mathias Agopian | ff615cc | 2012-02-24 14:58:36 -0800 | [diff] [blame] | 252 |         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] | 253 |         return BAD_VALUE; | 
 | 254 |     } | 
 | 255 |  | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 256 |     mFormat = format; | 
| Mathias Agopian | eff062c | 2010-08-25 14:59:15 -0700 | [diff] [blame] | 257 |  | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 258 |     mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 259 |     mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 260 |     mCurrentOpacity = getOpacityForFormat(format); | 
 | 261 |  | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 262 |     mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); | 
 | 263 |     mSurfaceFlingerConsumer->setDefaultBufferFormat(format); | 
 | 264 |     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); | 
| Mathias Agopian | ca99fb8 | 2010-04-14 16:43:44 -0700 | [diff] [blame] | 265 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 266 |     return NO_ERROR; | 
 | 267 | } | 
 | 268 |  | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 269 | sp<IBinder> Layer::getHandle() { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 270 |     Mutex::Autolock _l(mLock); | 
 | 271 |  | 
 | 272 |     LOG_ALWAYS_FATAL_IF(mHasSurface, | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 273 |             "Layer::getHandle() has already been called"); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 274 |  | 
 | 275 |     mHasSurface = true; | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 276 |  | 
 | 277 |     /* | 
 | 278 |      * The layer handle is just a BBinder object passed to the client | 
 | 279 |      * (remote process) -- we don't keep any reference on our side such that | 
 | 280 |      * the dtor is called when the remote side let go of its reference. | 
 | 281 |      * | 
 | 282 |      * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for | 
 | 283 |      * this layer when the handle is destroyed. | 
 | 284 |      */ | 
 | 285 |  | 
 | 286 |     class Handle : public BBinder, public LayerCleaner { | 
 | 287 |         wp<const Layer> mOwner; | 
 | 288 |     public: | 
 | 289 |         Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer) | 
 | 290 |             : LayerCleaner(flinger, layer), mOwner(layer) { | 
 | 291 |         } | 
 | 292 |     }; | 
 | 293 |  | 
 | 294 |     return new Handle(mFlinger, this); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 295 | } | 
 | 296 |  | 
| Dan Stoza | b9b0883 | 2014-03-13 11:55:57 -0700 | [diff] [blame] | 297 | sp<IGraphicBufferProducer> Layer::getProducer() const { | 
 | 298 |     return mProducer; | 
| Mathias Agopian | 4d9b822 | 2013-03-12 17:11:48 -0700 | [diff] [blame] | 299 | } | 
 | 300 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 301 | // --------------------------------------------------------------------------- | 
 | 302 | // h/w composer set-up | 
 | 303 | // --------------------------------------------------------------------------- | 
 | 304 |  | 
| Mathias Agopian | a8bca8d | 2013-02-27 22:03:19 -0800 | [diff] [blame] | 305 | Rect Layer::getContentCrop() const { | 
 | 306 |     // this is the crop rectangle that applies to the buffer | 
 | 307 |     // itself (as opposed to the window) | 
| Jamie Gennis | f15a83f | 2012-05-10 20:43:55 -0700 | [diff] [blame] | 308 |     Rect crop; | 
 | 309 |     if (!mCurrentCrop.isEmpty()) { | 
| Mathias Agopian | a8bca8d | 2013-02-27 22:03:19 -0800 | [diff] [blame] | 310 |         // if the buffer crop is defined, we use that | 
| Jamie Gennis | f15a83f | 2012-05-10 20:43:55 -0700 | [diff] [blame] | 311 |         crop = mCurrentCrop; | 
| Mathias Agopian | a8bca8d | 2013-02-27 22:03:19 -0800 | [diff] [blame] | 312 |     } else if (mActiveBuffer != NULL) { | 
 | 313 |         // otherwise we use the whole buffer | 
 | 314 |         crop = mActiveBuffer->getBounds(); | 
| Jamie Gennis | f15a83f | 2012-05-10 20:43:55 -0700 | [diff] [blame] | 315 |     } else { | 
| Mathias Agopian | a8bca8d | 2013-02-27 22:03:19 -0800 | [diff] [blame] | 316 |         // 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] | 317 |         crop.makeInvalid(); | 
| Jamie Gennis | f15a83f | 2012-05-10 20:43:55 -0700 | [diff] [blame] | 318 |     } | 
| Jamie Gennis | f15a83f | 2012-05-10 20:43:55 -0700 | [diff] [blame] | 319 |     return crop; | 
 | 320 | } | 
 | 321 |  | 
| Mathias Agopian | f3e85d4 | 2013-05-10 18:01:12 -0700 | [diff] [blame] | 322 | static Rect reduce(const Rect& win, const Region& exclude) { | 
 | 323 |     if (CC_LIKELY(exclude.isEmpty())) { | 
 | 324 |         return win; | 
 | 325 |     } | 
 | 326 |     if (exclude.isRect()) { | 
 | 327 |         return win.reduce(exclude.getBounds()); | 
 | 328 |     } | 
 | 329 |     return Region(win).subtract(exclude).getBounds(); | 
 | 330 | } | 
 | 331 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 332 | Rect Layer::computeBounds() const { | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 333 |     const Layer::State& s(getDrawingState()); | 
| Michael Lentine | 6c925ed | 2014-09-26 17:55:01 -0700 | [diff] [blame] | 334 |     return computeBounds(s.activeTransparentRegion); | 
 | 335 | } | 
 | 336 |  | 
 | 337 | Rect Layer::computeBounds(const Region& activeTransparentRegion) const { | 
 | 338 |     const Layer::State& s(getDrawingState()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 339 |     Rect win(s.active.w, s.active.h); | 
 | 340 |     if (!s.active.crop.isEmpty()) { | 
 | 341 |         win.intersect(s.active.crop, &win); | 
 | 342 |     } | 
| Mathias Agopian | 6c7f25a | 2013-05-09 20:37:10 -0700 | [diff] [blame] | 343 |     // subtract the transparent region and snap to the bounds | 
| Michael Lentine | 6c925ed | 2014-09-26 17:55:01 -0700 | [diff] [blame] | 344 |     return reduce(win, activeTransparentRegion); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 345 | } | 
 | 346 |  | 
| Mathias Agopian | 6b44267 | 2013-07-09 21:24:52 -0700 | [diff] [blame] | 347 | FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 348 |     // the content crop is the area of the content that gets scaled to the | 
 | 349 |     // layer's size. | 
| Mathias Agopian | 6b44267 | 2013-07-09 21:24:52 -0700 | [diff] [blame] | 350 |     FloatRect crop(getContentCrop()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 351 |  | 
 | 352 |     // the active.crop is the area of the window that gets cropped, but not | 
 | 353 |     // scaled in any ways. | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 354 |     const State& s(getDrawingState()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 355 |  | 
 | 356 |     // apply the projection's clipping to the window crop in | 
 | 357 |     // layerstack space, and convert-back to layer space. | 
| Mathias Agopian | 6b44267 | 2013-07-09 21:24:52 -0700 | [diff] [blame] | 358 |     // if there are no window scaling involved, this operation will map to full | 
 | 359 |     // pixels in the buffer. | 
 | 360 |     // FIXME: the 3 lines below can produce slightly incorrect clipping when we have | 
 | 361 |     // 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] | 362 |  | 
 | 363 |     Rect activeCrop(s.active.w, s.active.h); | 
 | 364 |     if (!s.active.crop.isEmpty()) { | 
 | 365 |         activeCrop = s.active.crop; | 
 | 366 |     } | 
 | 367 |  | 
 | 368 |     activeCrop = s.transform.transform(activeCrop); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 369 |     activeCrop.intersect(hw->getViewport(), &activeCrop); | 
 | 370 |     activeCrop = s.transform.inverse().transform(activeCrop); | 
 | 371 |  | 
| Michael Lentine | 28ea217 | 2014-11-19 18:32:37 -0800 | [diff] [blame] | 372 |     // This needs to be here as transform.transform(Rect) computes the | 
 | 373 |     // transformed rect and then takes the bounding box of the result before | 
 | 374 |     // returning. This means | 
 | 375 |     // transform.inverse().transform(transform.transform(Rect)) != Rect | 
 | 376 |     // in which case we need to make sure the final rect is clipped to the | 
 | 377 |     // display bounds. | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 378 |     activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); | 
 | 379 |  | 
| Mathias Agopian | f3e85d4 | 2013-05-10 18:01:12 -0700 | [diff] [blame] | 380 |     // subtract the transparent region and snap to the bounds | 
 | 381 |     activeCrop = reduce(activeCrop, s.activeTransparentRegion); | 
 | 382 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 383 |     if (!activeCrop.isEmpty()) { | 
 | 384 |         // Transform the window crop to match the buffer coordinate system, | 
 | 385 |         // which means using the inverse of the current transform set on the | 
 | 386 |         // SurfaceFlingerConsumer. | 
| Mathias Agopian | 6b44267 | 2013-07-09 21:24:52 -0700 | [diff] [blame] | 387 |         uint32_t invTransform = mCurrentTransform; | 
| Michael Lentine | f755140 | 2014-08-18 16:35:43 -0700 | [diff] [blame] | 388 |         if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { | 
 | 389 |             /* | 
 | 390 |              * the code below applies the display's inverse transform to the buffer | 
 | 391 |              */ | 
 | 392 |             uint32_t invTransformOrient = hw->getOrientationTransform(); | 
 | 393 |             // calculate the inverse transform | 
 | 394 |             if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) { | 
 | 395 |                 invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | | 
 | 396 |                         NATIVE_WINDOW_TRANSFORM_FLIP_H; | 
| Michael Lentine | 1440963 | 2014-08-19 11:27:30 -0700 | [diff] [blame] | 397 |                 // If the transform has been rotated the axis of flip has been swapped | 
 | 398 |                 // so we need to swap which flip operations we are performing | 
 | 399 |                 bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0; | 
 | 400 |                 bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0; | 
 | 401 |                 if (is_h_flipped != is_v_flipped) { | 
 | 402 |                     invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | | 
 | 403 |                             NATIVE_WINDOW_TRANSFORM_FLIP_H; | 
 | 404 |                 } | 
| Michael Lentine | f755140 | 2014-08-18 16:35:43 -0700 | [diff] [blame] | 405 |             } | 
 | 406 |             // and apply to the current transform | 
 | 407 |             invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation(); | 
 | 408 |         } | 
 | 409 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 410 |         int winWidth = s.active.w; | 
 | 411 |         int winHeight = s.active.h; | 
 | 412 |         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { | 
| Michael Lentine | 7b90258 | 2014-08-19 18:14:06 -0700 | [diff] [blame] | 413 |             // If the activeCrop has been rotate the ends are rotated but not | 
 | 414 |             // the space itself so when transforming ends back we can't rely on | 
 | 415 |             // a modification of the axes of rotation. To account for this we | 
 | 416 |             // need to reorient the inverse rotation in terms of the current | 
 | 417 |             // axes of rotation. | 
 | 418 |             bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0; | 
 | 419 |             bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0; | 
 | 420 |             if (is_h_flipped == is_v_flipped) { | 
 | 421 |                 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | | 
 | 422 |                         NATIVE_WINDOW_TRANSFORM_FLIP_H; | 
 | 423 |             } | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 424 |             winWidth = s.active.h; | 
 | 425 |             winHeight = s.active.w; | 
 | 426 |         } | 
 | 427 |         const Rect winCrop = activeCrop.transform( | 
| Michael Lentine | f755140 | 2014-08-18 16:35:43 -0700 | [diff] [blame] | 428 |                 invTransform, s.active.w, s.active.h); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 429 |  | 
| Mathias Agopian | 6b44267 | 2013-07-09 21:24:52 -0700 | [diff] [blame] | 430 |         // below, crop is intersected with winCrop expressed in crop's coordinate space | 
 | 431 |         float xScale = crop.getWidth()  / float(winWidth); | 
 | 432 |         float yScale = crop.getHeight() / float(winHeight); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 433 |  | 
| Michael Lentine | f755140 | 2014-08-18 16:35:43 -0700 | [diff] [blame] | 434 |         float insetL = winCrop.left                 * xScale; | 
 | 435 |         float insetT = winCrop.top                  * yScale; | 
 | 436 |         float insetR = (winWidth - winCrop.right )  * xScale; | 
 | 437 |         float insetB = (winHeight - winCrop.bottom) * yScale; | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 438 |  | 
 | 439 |         crop.left   += insetL; | 
 | 440 |         crop.top    += insetT; | 
 | 441 |         crop.right  -= insetR; | 
 | 442 |         crop.bottom -= insetB; | 
 | 443 |     } | 
 | 444 |     return crop; | 
 | 445 | } | 
 | 446 |  | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 447 | void Layer::setGeometry( | 
| Mathias Agopian | 4297734 | 2012-08-05 00:40:46 -0700 | [diff] [blame] | 448 |     const sp<const DisplayDevice>& hw, | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 449 |         HWComposer::HWCLayerInterface& layer) | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 450 | { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 451 |     layer.setDefaultState(); | 
| Mathias Agopian | a537c0f | 2011-08-02 15:51:37 -0700 | [diff] [blame] | 452 |  | 
| Mathias Agopian | 3e8b853 | 2012-05-13 20:42:01 -0700 | [diff] [blame] | 453 |     // enable this layer | 
 | 454 |     layer.setSkip(false); | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 455 |  | 
| Jamie Gennis | dd3cb84 | 2012-10-19 18:19:11 -0700 | [diff] [blame] | 456 |     if (isSecure() && !hw->isSecure()) { | 
 | 457 |         layer.setSkip(true); | 
 | 458 |     } | 
 | 459 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 460 |     // this gives us only the "orientation" component of the transform | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 461 |     const State& s(getDrawingState()); | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 462 |     if (!isOpaque(s) || s.alpha != 0xFF) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 463 |         layer.setBlending(mPremultipliedAlpha ? | 
 | 464 |                 HWC_BLENDING_PREMULT : | 
 | 465 |                 HWC_BLENDING_COVERAGE); | 
 | 466 |     } | 
 | 467 |  | 
 | 468 |     // apply the layer's transform, followed by the display's global transform | 
 | 469 |     // here we're guaranteed that the layer's transform preserves rects | 
| Michael Lentine | 6c925ed | 2014-09-26 17:55:01 -0700 | [diff] [blame] | 470 |     Region activeTransparentRegion(s.activeTransparentRegion); | 
 | 471 |     if (!s.active.crop.isEmpty()) { | 
 | 472 |         Rect activeCrop(s.active.crop); | 
 | 473 |         activeCrop = s.transform.transform(activeCrop); | 
 | 474 |         activeCrop.intersect(hw->getViewport(), &activeCrop); | 
 | 475 |         activeCrop = s.transform.inverse().transform(activeCrop); | 
| Michael Lentine | 28ea217 | 2014-11-19 18:32:37 -0800 | [diff] [blame] | 476 |         // This needs to be here as transform.transform(Rect) computes the | 
 | 477 |         // transformed rect and then takes the bounding box of the result before | 
 | 478 |         // returning. This means | 
 | 479 |         // transform.inverse().transform(transform.transform(Rect)) != Rect | 
 | 480 |         // in which case we need to make sure the final rect is clipped to the | 
 | 481 |         // display bounds. | 
 | 482 |         activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); | 
| Michael Lentine | 6c925ed | 2014-09-26 17:55:01 -0700 | [diff] [blame] | 483 |         // mark regions outside the crop as transparent | 
 | 484 |         activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top)); | 
 | 485 |         activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, | 
 | 486 |                 s.active.w, s.active.h)); | 
 | 487 |         activeTransparentRegion.orSelf(Rect(0, activeCrop.top, | 
 | 488 |                 activeCrop.left, activeCrop.bottom)); | 
 | 489 |         activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top, | 
 | 490 |                 s.active.w, activeCrop.bottom)); | 
 | 491 |     } | 
 | 492 |     Rect frame(s.transform.transform(computeBounds(activeTransparentRegion))); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 493 |     frame.intersect(hw->getViewport(), &frame); | 
 | 494 |     const Transform& tr(hw->getTransform()); | 
 | 495 |     layer.setFrame(tr.transform(frame)); | 
 | 496 |     layer.setCrop(computeCrop(hw)); | 
| Mathias Agopian | 9f8386e | 2013-01-29 18:56:42 -0800 | [diff] [blame] | 497 |     layer.setPlaneAlpha(s.alpha); | 
 | 498 |  | 
| Mathias Agopian | 29a367b | 2011-07-12 14:51:45 -0700 | [diff] [blame] | 499 |     /* | 
 | 500 |      * Transformations are applied in this order: | 
 | 501 |      * 1) buffer orientation/flip/mirror | 
 | 502 |      * 2) state transformation (window manager) | 
 | 503 |      * 3) layer orientation (screen orientation) | 
 | 504 |      * (NOTE: the matrices are multiplied in reverse order) | 
 | 505 |      */ | 
 | 506 |  | 
 | 507 |     const Transform bufferOrientation(mCurrentTransform); | 
| Mathias Agopian | c1c05de | 2013-09-17 23:45:22 -0700 | [diff] [blame] | 508 |     Transform transform(tr * s.transform * bufferOrientation); | 
 | 509 |  | 
 | 510 |     if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { | 
 | 511 |         /* | 
 | 512 |          * the code below applies the display's inverse transform to the buffer | 
 | 513 |          */ | 
 | 514 |         uint32_t invTransform = hw->getOrientationTransform(); | 
| Michael Lentine | 1440963 | 2014-08-19 11:27:30 -0700 | [diff] [blame] | 515 |         uint32_t t_orientation = transform.getOrientation(); | 
| Mathias Agopian | c1c05de | 2013-09-17 23:45:22 -0700 | [diff] [blame] | 516 |         // calculate the inverse transform | 
 | 517 |         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { | 
 | 518 |             invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | | 
 | 519 |                     NATIVE_WINDOW_TRANSFORM_FLIP_H; | 
| Michael Lentine | 1440963 | 2014-08-19 11:27:30 -0700 | [diff] [blame] | 520 |             // If the transform has been rotated the axis of flip has been swapped | 
 | 521 |             // so we need to swap which flip operations we are performing | 
 | 522 |             bool is_h_flipped = (t_orientation & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0; | 
 | 523 |             bool is_v_flipped = (t_orientation & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0; | 
 | 524 |             if (is_h_flipped != is_v_flipped) { | 
 | 525 |                 t_orientation ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | | 
 | 526 |                         NATIVE_WINDOW_TRANSFORM_FLIP_H; | 
 | 527 |             } | 
| Mathias Agopian | c1c05de | 2013-09-17 23:45:22 -0700 | [diff] [blame] | 528 |         } | 
 | 529 |         // and apply to the current transform | 
| Michael Lentine | 1440963 | 2014-08-19 11:27:30 -0700 | [diff] [blame] | 530 |         transform = Transform(t_orientation) * Transform(invTransform); | 
| Mathias Agopian | c1c05de | 2013-09-17 23:45:22 -0700 | [diff] [blame] | 531 |     } | 
| Mathias Agopian | 29a367b | 2011-07-12 14:51:45 -0700 | [diff] [blame] | 532 |  | 
 | 533 |     // this gives us only the "orientation" component of the transform | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 534 |     const uint32_t orientation = transform.getOrientation(); | 
 | 535 |     if (orientation & Transform::ROT_INVALID) { | 
 | 536 |         // we can only handle simple transformation | 
| Mathias Agopian | 3e8b853 | 2012-05-13 20:42:01 -0700 | [diff] [blame] | 537 |         layer.setSkip(true); | 
| Mathias Agopian | a537c0f | 2011-08-02 15:51:37 -0700 | [diff] [blame] | 538 |     } else { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 539 |         layer.setTransform(orientation); | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 540 |     } | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 541 | } | 
 | 542 |  | 
| Mathias Agopian | 4297734 | 2012-08-05 00:40:46 -0700 | [diff] [blame] | 543 | void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 544 |         HWComposer::HWCLayerInterface& layer) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 545 |     // we have to set the visible region on every frame because | 
 | 546 |     // we currently free it during onLayerDisplayed(), which is called | 
 | 547 |     // after HWComposer::commit() -- every frame. | 
 | 548 |     // Apply this display's projection's viewport to the visible region | 
 | 549 |     // before giving it to the HWC HAL. | 
 | 550 |     const Transform& tr = hw->getTransform(); | 
 | 551 |     Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); | 
 | 552 |     layer.setVisibleRegionScreen(visible); | 
| Dan Stoza | db4850c | 2015-06-25 16:10:18 -0700 | [diff] [blame] | 553 |     layer.setSurfaceDamage(surfaceDamageRegion); | 
| Dan Stoza | ee44edd | 2015-03-23 15:50:23 -0700 | [diff] [blame] | 554 |  | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 555 |     if (mSidebandStream.get()) { | 
 | 556 |         layer.setSidebandStream(mSidebandStream); | 
 | 557 |     } else { | 
 | 558 |         // NOTE: buffer can be NULL if the client never drew into this | 
 | 559 |         // layer yet, or if we ran out of memory | 
 | 560 |         layer.setBuffer(mActiveBuffer); | 
 | 561 |     } | 
| Jesse Hall | c5c5a14 | 2012-07-02 16:49:28 -0700 | [diff] [blame] | 562 | } | 
| Jesse Hall | dc5b485 | 2012-06-29 15:21:18 -0700 | [diff] [blame] | 563 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 564 | void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */, | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 565 |         HWComposer::HWCLayerInterface& layer) { | 
| Jesse Hall | c5c5a14 | 2012-07-02 16:49:28 -0700 | [diff] [blame] | 566 |     int fenceFd = -1; | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 567 |  | 
 | 568 |     // TODO: there is a possible optimization here: we only need to set the | 
 | 569 |     // acquire fence the first time a new buffer is acquired on EACH display. | 
 | 570 |  | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 571 |     if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) { | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 572 |         sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence(); | 
| Jamie Gennis | 1df8c34 | 2012-12-20 14:05:45 -0800 | [diff] [blame] | 573 |         if (fence->isValid()) { | 
| Jesse Hall | c5c5a14 | 2012-07-02 16:49:28 -0700 | [diff] [blame] | 574 |             fenceFd = fence->dup(); | 
| Jesse Hall | dc5b485 | 2012-06-29 15:21:18 -0700 | [diff] [blame] | 575 |             if (fenceFd == -1) { | 
 | 576 |                 ALOGW("failed to dup layer fence, skipping sync: %d", errno); | 
 | 577 |             } | 
| Jesse Hall | dc5b485 | 2012-06-29 15:21:18 -0700 | [diff] [blame] | 578 |         } | 
| Jesse Hall | dc5b485 | 2012-06-29 15:21:18 -0700 | [diff] [blame] | 579 |     } | 
| Jesse Hall | c5c5a14 | 2012-07-02 16:49:28 -0700 | [diff] [blame] | 580 |     layer.setAcquireFenceFd(fenceFd); | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 581 | } | 
 | 582 |  | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 583 | Rect Layer::getPosition( | 
 | 584 |     const sp<const DisplayDevice>& hw) | 
 | 585 | { | 
 | 586 |     // this gives us only the "orientation" component of the transform | 
 | 587 |     const State& s(getCurrentState()); | 
 | 588 |  | 
 | 589 |     // apply the layer's transform, followed by the display's global transform | 
 | 590 |     // here we're guaranteed that the layer's transform preserves rects | 
 | 591 |     Rect win(s.active.w, s.active.h); | 
 | 592 |     if (!s.active.crop.isEmpty()) { | 
 | 593 |         win.intersect(s.active.crop, &win); | 
 | 594 |     } | 
 | 595 |     // subtract the transparent region and snap to the bounds | 
 | 596 |     Rect bounds = reduce(win, s.activeTransparentRegion); | 
 | 597 |     Rect frame(s.transform.transform(bounds)); | 
 | 598 |     frame.intersect(hw->getViewport(), &frame); | 
 | 599 |     const Transform& tr(hw->getTransform()); | 
 | 600 |     return Rect(tr.transform(frame)); | 
 | 601 | } | 
 | 602 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 603 | // --------------------------------------------------------------------------- | 
 | 604 | // drawing... | 
 | 605 | // --------------------------------------------------------------------------- | 
 | 606 |  | 
 | 607 | void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const { | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 608 |     onDraw(hw, clip, false); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 609 | } | 
 | 610 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 611 | void Layer::draw(const sp<const DisplayDevice>& hw, | 
 | 612 |         bool useIdentityTransform) const { | 
 | 613 |     onDraw(hw, Region(hw->bounds()), useIdentityTransform); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 614 | } | 
 | 615 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 616 | void Layer::draw(const sp<const DisplayDevice>& hw) const { | 
 | 617 |     onDraw(hw, Region(hw->bounds()), false); | 
 | 618 | } | 
 | 619 |  | 
 | 620 | void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, | 
 | 621 |         bool useIdentityTransform) const | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 622 | { | 
| Jamie Gennis | 1c8e95c | 2012-02-23 19:27:23 -0800 | [diff] [blame] | 623 |     ATRACE_CALL(); | 
 | 624 |  | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 625 |     if (CC_UNLIKELY(mActiveBuffer == 0)) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 626 |         // the texture has not been created yet, this Layer has | 
| Mathias Agopian | 179169e | 2010-05-06 20:21:45 -0700 | [diff] [blame] | 627 |         // in fact never been drawn into. This happens frequently with | 
 | 628 |         // SurfaceView because the WindowManager can't know when the client | 
 | 629 |         // has drawn the first time. | 
 | 630 |  | 
 | 631 |         // If there is nothing under us, we paint the screen in black, otherwise | 
 | 632 |         // we just skip this update. | 
 | 633 |  | 
 | 634 |         // figure out if there is something below us | 
 | 635 |         Region under; | 
| Mathias Agopian | f7ae69d | 2011-08-23 12:34:29 -0700 | [diff] [blame] | 636 |         const SurfaceFlinger::LayerVector& drawingLayers( | 
 | 637 |                 mFlinger->mDrawingState.layersSortedByZ); | 
| Mathias Agopian | 179169e | 2010-05-06 20:21:45 -0700 | [diff] [blame] | 638 |         const size_t count = drawingLayers.size(); | 
 | 639 |         for (size_t i=0 ; i<count ; ++i) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 640 |             const sp<Layer>& layer(drawingLayers[i]); | 
 | 641 |             if (layer.get() == static_cast<Layer const*>(this)) | 
| Mathias Agopian | 179169e | 2010-05-06 20:21:45 -0700 | [diff] [blame] | 642 |                 break; | 
| Mathias Agopian | 4297734 | 2012-08-05 00:40:46 -0700 | [diff] [blame] | 643 |             under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); | 
| Mathias Agopian | 179169e | 2010-05-06 20:21:45 -0700 | [diff] [blame] | 644 |         } | 
 | 645 |         // if not everything below us is covered, we plug the holes! | 
 | 646 |         Region holes(clip.subtract(under)); | 
 | 647 |         if (!holes.isEmpty()) { | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 648 |             clearWithOpenGL(hw, holes, 0, 0, 0, 1); | 
| Mathias Agopian | 179169e | 2010-05-06 20:21:45 -0700 | [diff] [blame] | 649 |         } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 650 |         return; | 
 | 651 |     } | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 652 |  | 
| Andy McFadden | 97eba89 | 2012-12-11 15:21:45 -0800 | [diff] [blame] | 653 |     // Bind the current buffer to the GL texture, and wait for it to be | 
 | 654 |     // ready for us to draw into. | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 655 |     status_t err = mSurfaceFlingerConsumer->bindTextureImage(); | 
 | 656 |     if (err != NO_ERROR) { | 
| Andy McFadden | 97eba89 | 2012-12-11 15:21:45 -0800 | [diff] [blame] | 657 |         ALOGW("onDraw: bindTextureImage failed (err=%d)", err); | 
| Jesse Hall | dc5b485 | 2012-06-29 15:21:18 -0700 | [diff] [blame] | 658 |         // Go ahead and draw the buffer anyway; no matter what we do the screen | 
 | 659 |         // is probably going to have something visibly wrong. | 
 | 660 |     } | 
 | 661 |  | 
| Jamie Gennis | dd3cb84 | 2012-10-19 18:19:11 -0700 | [diff] [blame] | 662 |     bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); | 
 | 663 |  | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 664 |     RenderEngine& engine(mFlinger->getRenderEngine()); | 
 | 665 |  | 
| Jamie Gennis | dd3cb84 | 2012-10-19 18:19:11 -0700 | [diff] [blame] | 666 |     if (!blackOutLayer) { | 
| Jamie Gennis | cbb1a95 | 2012-05-08 17:05:52 -0700 | [diff] [blame] | 667 |         // TODO: we could be more subtle with isFixedSize() | 
| Mathias Agopian | eba8c68 | 2012-09-19 23:14:45 -0700 | [diff] [blame] | 668 |         const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); | 
| Jamie Gennis | cbb1a95 | 2012-05-08 17:05:52 -0700 | [diff] [blame] | 669 |  | 
 | 670 |         // Query the texture matrix given our current filtering mode. | 
 | 671 |         float textureMatrix[16]; | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 672 |         mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); | 
 | 673 |         mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); | 
| Jamie Gennis | cbb1a95 | 2012-05-08 17:05:52 -0700 | [diff] [blame] | 674 |  | 
| Mathias Agopian | c1c05de | 2013-09-17 23:45:22 -0700 | [diff] [blame] | 675 |         if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { | 
 | 676 |  | 
 | 677 |             /* | 
 | 678 |              * the code below applies the display's inverse transform to the texture transform | 
 | 679 |              */ | 
 | 680 |  | 
 | 681 |             // create a 4x4 transform matrix from the display transform flags | 
 | 682 |             const mat4 flipH(-1,0,0,0,  0,1,0,0, 0,0,1,0, 1,0,0,1); | 
 | 683 |             const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1); | 
 | 684 |             const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1); | 
 | 685 |  | 
 | 686 |             mat4 tr; | 
 | 687 |             uint32_t transform = hw->getOrientationTransform(); | 
 | 688 |             if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) | 
 | 689 |                 tr = tr * rot90; | 
 | 690 |             if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) | 
 | 691 |                 tr = tr * flipH; | 
 | 692 |             if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) | 
 | 693 |                 tr = tr * flipV; | 
 | 694 |  | 
 | 695 |             // calculate the inverse | 
 | 696 |             tr = inverse(tr); | 
 | 697 |  | 
 | 698 |             // and finally apply it to the original texture matrix | 
 | 699 |             const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr); | 
 | 700 |             memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix)); | 
 | 701 |         } | 
 | 702 |  | 
| Jamie Gennis | cbb1a95 | 2012-05-08 17:05:52 -0700 | [diff] [blame] | 703 |         // Set things up for texturing. | 
| Mathias Agopian | 49457ac | 2013-08-14 18:20:17 -0700 | [diff] [blame] | 704 |         mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); | 
 | 705 |         mTexture.setFiltering(useFiltering); | 
 | 706 |         mTexture.setMatrix(textureMatrix); | 
 | 707 |  | 
 | 708 |         engine.setupLayerTexturing(mTexture); | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 709 |     } else { | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 710 |         engine.setupLayerBlackedOut(); | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 711 |     } | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 712 |     drawWithOpenGL(hw, clip, useIdentityTransform); | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 713 |     engine.disableTexturing(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 714 | } | 
 | 715 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 716 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 717 | void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, | 
 | 718 |         const Region& /* clip */, float red, float green, float blue, | 
 | 719 |         float alpha) const | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 720 | { | 
| Mathias Agopian | 19733a3 | 2013-08-28 18:13:56 -0700 | [diff] [blame] | 721 |     RenderEngine& engine(mFlinger->getRenderEngine()); | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 722 |     computeGeometry(hw, mMesh, false); | 
| Mathias Agopian | 19733a3 | 2013-08-28 18:13:56 -0700 | [diff] [blame] | 723 |     engine.setupFillWithColor(red, green, blue, alpha); | 
 | 724 |     engine.drawMesh(mMesh); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 725 | } | 
 | 726 |  | 
 | 727 | void Layer::clearWithOpenGL( | 
 | 728 |         const sp<const DisplayDevice>& hw, const Region& clip) const { | 
 | 729 |     clearWithOpenGL(hw, clip, 0,0,0,0); | 
 | 730 | } | 
 | 731 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 732 | void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, | 
 | 733 |         const Region& /* clip */, bool useIdentityTransform) const { | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 734 |     const State& s(getDrawingState()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 735 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 736 |     computeGeometry(hw, mMesh, useIdentityTransform); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 737 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 738 |     /* | 
 | 739 |      * NOTE: the way we compute the texture coordinates here produces | 
 | 740 |      * different results than when we take the HWC path -- in the later case | 
 | 741 |      * the "source crop" is rounded to texel boundaries. | 
 | 742 |      * This can produce significantly different results when the texture | 
 | 743 |      * is scaled by a large amount. | 
 | 744 |      * | 
 | 745 |      * The GL code below is more logical (imho), and the difference with | 
 | 746 |      * 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] | 747 |      * is suspend is whether we should ignore this problem or revert to | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 748 |      * GL composition when a buffer scaling is applied (maybe with some | 
 | 749 |      * minimal value)? Or, we could make GL behave like HWC -- but this feel | 
 | 750 |      * like more of a hack. | 
 | 751 |      */ | 
 | 752 |     const Rect win(computeBounds()); | 
 | 753 |  | 
| Mathias Agopian | 3f84483 | 2013-08-07 21:24:32 -0700 | [diff] [blame] | 754 |     float left   = float(win.left)   / float(s.active.w); | 
 | 755 |     float top    = float(win.top)    / float(s.active.h); | 
 | 756 |     float right  = float(win.right)  / float(s.active.w); | 
 | 757 |     float bottom = float(win.bottom) / float(s.active.h); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 758 |  | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 759 |     // TODO: we probably want to generate the texture coords with the mesh | 
 | 760 |     // here we assume that we only have 4 vertices | 
| Mathias Agopian | ff2ed70 | 2013-09-01 21:36:12 -0700 | [diff] [blame] | 761 |     Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>()); | 
 | 762 |     texCoords[0] = vec2(left, 1.0f - top); | 
 | 763 |     texCoords[1] = vec2(left, 1.0f - bottom); | 
 | 764 |     texCoords[2] = vec2(right, 1.0f - bottom); | 
 | 765 |     texCoords[3] = vec2(right, 1.0f - top); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 766 |  | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 767 |     RenderEngine& engine(mFlinger->getRenderEngine()); | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 768 |     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha); | 
| Mathias Agopian | 5cdc899 | 2013-08-13 20:51:23 -0700 | [diff] [blame] | 769 |     engine.drawMesh(mMesh); | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 770 |     engine.disableBlending(); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 771 | } | 
 | 772 |  | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 773 | uint32_t Layer::getProducerStickyTransform() const { | 
 | 774 |     int producerStickyTransform = 0; | 
 | 775 |     int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); | 
 | 776 |     if (ret != OK) { | 
 | 777 |         ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, | 
 | 778 |                 strerror(-ret), ret); | 
 | 779 |         return 0; | 
 | 780 |     } | 
 | 781 |     return static_cast<uint32_t>(producerStickyTransform); | 
 | 782 | } | 
 | 783 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 784 | void Layer::setFiltering(bool filtering) { | 
 | 785 |     mFiltering = filtering; | 
 | 786 | } | 
 | 787 |  | 
 | 788 | bool Layer::getFiltering() const { | 
 | 789 |     return mFiltering; | 
 | 790 | } | 
 | 791 |  | 
| Eric Hassold | ac45e6b | 2011-02-10 14:41:26 -0800 | [diff] [blame] | 792 | // As documented in libhardware header, formats in the range | 
 | 793 | // 0x100 - 0x1FF are specific to the HAL implementation, and | 
 | 794 | // are known to have no alpha channel | 
 | 795 | // TODO: move definition for device-specific range into | 
 | 796 | // hardware.h, instead of using hard-coded values here. | 
 | 797 | #define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) | 
 | 798 |  | 
| Mathias Agopian | 5773d3f | 2013-07-25 19:24:31 -0700 | [diff] [blame] | 799 | bool Layer::getOpacityForFormat(uint32_t format) { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 800 |     if (HARDWARE_IS_DEVICE_FORMAT(format)) { | 
 | 801 |         return true; | 
| Eric Hassold | ac45e6b | 2011-02-10 14:41:26 -0800 | [diff] [blame] | 802 |     } | 
| Mathias Agopian | 5773d3f | 2013-07-25 19:24:31 -0700 | [diff] [blame] | 803 |     switch (format) { | 
 | 804 |         case HAL_PIXEL_FORMAT_RGBA_8888: | 
 | 805 |         case HAL_PIXEL_FORMAT_BGRA_8888: | 
| Mathias Agopian | dd53371 | 2013-07-26 15:31:39 -0700 | [diff] [blame] | 806 |             return false; | 
| Mathias Agopian | 5773d3f | 2013-07-25 19:24:31 -0700 | [diff] [blame] | 807 |     } | 
 | 808 |     // in all other case, we have no blending (also for unknown formats) | 
| Mathias Agopian | dd53371 | 2013-07-26 15:31:39 -0700 | [diff] [blame] | 809 |     return true; | 
| Eric Hassold | ac45e6b | 2011-02-10 14:41:26 -0800 | [diff] [blame] | 810 | } | 
 | 811 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 812 | // ---------------------------------------------------------------------------- | 
 | 813 | // local state | 
 | 814 | // ---------------------------------------------------------------------------- | 
 | 815 |  | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 816 | void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, | 
 | 817 |         bool useIdentityTransform) const | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 818 | { | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 819 |     const Layer::State& s(getDrawingState()); | 
| Dan Stoza | c701401 | 2014-02-14 15:03:43 -0800 | [diff] [blame] | 820 |     const Transform tr(useIdentityTransform ? | 
 | 821 |             hw->getTransform() : hw->getTransform() * s.transform); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 822 |     const uint32_t hw_h = hw->getHeight(); | 
 | 823 |     Rect win(s.active.w, s.active.h); | 
 | 824 |     if (!s.active.crop.isEmpty()) { | 
 | 825 |         win.intersect(s.active.crop, &win); | 
 | 826 |     } | 
| Mathias Agopian | 6c7f25a | 2013-05-09 20:37:10 -0700 | [diff] [blame] | 827 |     // subtract the transparent region and snap to the bounds | 
| Mathias Agopian | f3e85d4 | 2013-05-10 18:01:12 -0700 | [diff] [blame] | 828 |     win = reduce(win, s.activeTransparentRegion); | 
| Mathias Agopian | 3f84483 | 2013-08-07 21:24:32 -0700 | [diff] [blame] | 829 |  | 
| Mathias Agopian | ff2ed70 | 2013-09-01 21:36:12 -0700 | [diff] [blame] | 830 |     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); | 
 | 831 |     position[0] = tr.transform(win.left,  win.top); | 
 | 832 |     position[1] = tr.transform(win.left,  win.bottom); | 
 | 833 |     position[2] = tr.transform(win.right, win.bottom); | 
 | 834 |     position[3] = tr.transform(win.right, win.top); | 
| Mathias Agopian | 3f84483 | 2013-08-07 21:24:32 -0700 | [diff] [blame] | 835 |     for (size_t i=0 ; i<4 ; i++) { | 
| Mathias Agopian | 5cdc899 | 2013-08-13 20:51:23 -0700 | [diff] [blame] | 836 |         position[i].y = hw_h - position[i].y; | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 837 |     } | 
 | 838 | } | 
| Eric Hassold | ac45e6b | 2011-02-10 14:41:26 -0800 | [diff] [blame] | 839 |  | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 840 | bool Layer::isOpaque(const Layer::State& s) const | 
| Mathias Agopian | a7f6692 | 2010-05-26 22:08:52 -0700 | [diff] [blame] | 841 | { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 842 |     // if we don't have a buffer yet, we're translucent regardless of the | 
 | 843 |     // layer's opaque flag. | 
| Jamie Gennis | db5230f | 2011-07-28 14:54:07 -0700 | [diff] [blame] | 844 |     if (mActiveBuffer == 0) { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 845 |         return false; | 
| Jamie Gennis | db5230f | 2011-07-28 14:54:07 -0700 | [diff] [blame] | 846 |     } | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 847 |  | 
 | 848 |     // if the layer has the opaque flag, then we're always opaque, | 
 | 849 |     // otherwise we use the current buffer's format. | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 850 |     return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; | 
| Mathias Agopian | a7f6692 | 2010-05-26 22:08:52 -0700 | [diff] [blame] | 851 | } | 
 | 852 |  | 
| Dan Stoza | 2311608 | 2015-06-18 14:58:39 -0700 | [diff] [blame] | 853 | bool Layer::isSecure() const | 
 | 854 | { | 
 | 855 |     const Layer::State& s(mDrawingState); | 
 | 856 |     return (s.flags & layer_state_t::eLayerSecure); | 
 | 857 | } | 
 | 858 |  | 
| Jamie Gennis | 7a4d0df | 2011-03-09 17:05:02 -0800 | [diff] [blame] | 859 | bool Layer::isProtected() const | 
 | 860 | { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 861 |     const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); | 
| Jamie Gennis | 7a4d0df | 2011-03-09 17:05:02 -0800 | [diff] [blame] | 862 |     return (activeBuffer != 0) && | 
 | 863 |             (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); | 
 | 864 | } | 
| Mathias Agopian | b5b7f26 | 2010-05-07 15:58:44 -0700 | [diff] [blame] | 865 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 866 | bool Layer::isFixedSize() const { | 
 | 867 |     return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; | 
 | 868 | } | 
 | 869 |  | 
 | 870 | bool Layer::isCropped() const { | 
 | 871 |     return !mCurrentCrop.isEmpty(); | 
 | 872 | } | 
 | 873 |  | 
 | 874 | bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const { | 
 | 875 |     return mNeedsFiltering || hw->needsFiltering(); | 
 | 876 | } | 
 | 877 |  | 
 | 878 | void Layer::setVisibleRegion(const Region& visibleRegion) { | 
 | 879 |     // always called from main thread | 
 | 880 |     this->visibleRegion = visibleRegion; | 
 | 881 | } | 
 | 882 |  | 
 | 883 | void Layer::setCoveredRegion(const Region& coveredRegion) { | 
 | 884 |     // always called from main thread | 
 | 885 |     this->coveredRegion = coveredRegion; | 
 | 886 | } | 
 | 887 |  | 
 | 888 | void Layer::setVisibleNonTransparentRegion(const Region& | 
 | 889 |         setVisibleNonTransparentRegion) { | 
 | 890 |     // always called from main thread | 
 | 891 |     this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; | 
 | 892 | } | 
 | 893 |  | 
 | 894 | // ---------------------------------------------------------------------------- | 
 | 895 | // transaction | 
 | 896 | // ---------------------------------------------------------------------------- | 
 | 897 |  | 
 | 898 | uint32_t Layer::doTransaction(uint32_t flags) { | 
| Jamie Gennis | 1c8e95c | 2012-02-23 19:27:23 -0800 | [diff] [blame] | 899 |     ATRACE_CALL(); | 
 | 900 |  | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 901 |     const Layer::State& s(getDrawingState()); | 
 | 902 |     const Layer::State& c(getCurrentState()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 903 |  | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 904 |     const bool sizeChanged = (c.requested.w != s.requested.w) || | 
 | 905 |                              (c.requested.h != s.requested.h); | 
| Mathias Agopian | a138f89 | 2010-05-21 17:24:35 -0700 | [diff] [blame] | 906 |  | 
 | 907 |     if (sizeChanged) { | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 908 |         // 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] | 909 |         ALOGD_IF(DEBUG_RESIZE, | 
| Andy McFadden | 6905205 | 2012-09-14 16:10:11 -0700 | [diff] [blame] | 910 |                 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" | 
| Mathias Agopian | 419e196 | 2012-05-23 14:34:07 -0700 | [diff] [blame] | 911 |                 "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" | 
 | 912 |                 "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n" | 
 | 913 |                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" | 
 | 914 |                 "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n", | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 915 |                 this, getName().string(), mCurrentTransform, mCurrentScalingMode, | 
 | 916 |                 c.active.w, c.active.h, | 
 | 917 |                 c.active.crop.left, | 
 | 918 |                 c.active.crop.top, | 
 | 919 |                 c.active.crop.right, | 
 | 920 |                 c.active.crop.bottom, | 
 | 921 |                 c.active.crop.getWidth(), | 
 | 922 |                 c.active.crop.getHeight(), | 
 | 923 |                 c.requested.w, c.requested.h, | 
 | 924 |                 c.requested.crop.left, | 
 | 925 |                 c.requested.crop.top, | 
 | 926 |                 c.requested.crop.right, | 
 | 927 |                 c.requested.crop.bottom, | 
 | 928 |                 c.requested.crop.getWidth(), | 
 | 929 |                 c.requested.crop.getHeight(), | 
 | 930 |                 s.active.w, s.active.h, | 
 | 931 |                 s.active.crop.left, | 
 | 932 |                 s.active.crop.top, | 
 | 933 |                 s.active.crop.right, | 
 | 934 |                 s.active.crop.bottom, | 
 | 935 |                 s.active.crop.getWidth(), | 
 | 936 |                 s.active.crop.getHeight(), | 
 | 937 |                 s.requested.w, s.requested.h, | 
 | 938 |                 s.requested.crop.left, | 
 | 939 |                 s.requested.crop.top, | 
 | 940 |                 s.requested.crop.right, | 
 | 941 |                 s.requested.crop.bottom, | 
 | 942 |                 s.requested.crop.getWidth(), | 
 | 943 |                 s.requested.crop.getHeight()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 944 |  | 
| Jamie Gennis | 2a0d5b6 | 2011-09-26 16:54:44 -0700 | [diff] [blame] | 945 |         // record the new size, form this point on, when the client request | 
 | 946 |         // a buffer, it'll get the new size. | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 947 |         mSurfaceFlingerConsumer->setDefaultBufferSize( | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 948 |                 c.requested.w, c.requested.h); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 949 |     } | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 950 |  | 
| Mathias Agopian | 0cd545f | 2012-06-07 14:18:55 -0700 | [diff] [blame] | 951 |     if (!isFixedSize()) { | 
 | 952 |  | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 953 |         const bool resizePending = (c.requested.w != c.active.w) || | 
 | 954 |                                    (c.requested.h != c.active.h); | 
| Mathias Agopian | 0cd545f | 2012-06-07 14:18:55 -0700 | [diff] [blame] | 955 |  | 
| Dan Stoza | 9e9b044 | 2015-04-22 14:59:08 -0700 | [diff] [blame] | 956 |         if (resizePending && mSidebandStream == NULL) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 957 |             // don't let Layer::doTransaction update the drawing state | 
| Mathias Agopian | 0cd545f | 2012-06-07 14:18:55 -0700 | [diff] [blame] | 958 |             // if we have a pending resize, unless we are in fixed-size mode. | 
 | 959 |             // the drawing state will be updated only once we receive a buffer | 
 | 960 |             // with the correct size. | 
 | 961 |             // | 
 | 962 |             // in particular, we want to make sure the clip (which is part | 
 | 963 |             // of the geometry state) is latched together with the size but is | 
 | 964 |             // latched immediately when no resizing is involved. | 
| Dan Stoza | 9e9b044 | 2015-04-22 14:59:08 -0700 | [diff] [blame] | 965 |             // | 
 | 966 |             // If a sideband stream is attached, however, we want to skip this | 
 | 967 |             // optimization so that transactions aren't missed when a buffer | 
 | 968 |             // never arrives | 
| Mathias Agopian | 0cd545f | 2012-06-07 14:18:55 -0700 | [diff] [blame] | 969 |  | 
 | 970 |             flags |= eDontUpdateGeometryState; | 
 | 971 |         } | 
 | 972 |     } | 
 | 973 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 974 |     // always set active to requested, unless we're asked not to | 
 | 975 |     // this is used by Layer, which special cases resizes. | 
 | 976 |     if (flags & eDontUpdateGeometryState)  { | 
 | 977 |     } else { | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 978 |         Layer::State& editCurrentState(getCurrentState()); | 
 | 979 |         editCurrentState.active = c.requested; | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 980 |     } | 
 | 981 |  | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 982 |     if (s.active != c.active) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 983 |         // invalidate and recompute the visible regions if needed | 
 | 984 |         flags |= Layer::eVisibleRegion; | 
 | 985 |     } | 
 | 986 |  | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 987 |     if (c.sequence != s.sequence) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 988 |         // invalidate and recompute the visible regions if needed | 
 | 989 |         flags |= eVisibleRegion; | 
 | 990 |         this->contentDirty = true; | 
 | 991 |  | 
 | 992 |         // we may use linear filtering, if the matrix scales us | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 993 |         const uint8_t type = c.transform.getType(); | 
 | 994 |         mNeedsFiltering = (!c.transform.preserveRects() || | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 995 |                 (type >= Transform::SCALE)); | 
 | 996 |     } | 
 | 997 |  | 
 | 998 |     // Commit the transaction | 
 | 999 |     commitTransaction(); | 
 | 1000 |     return flags; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1001 | } | 
 | 1002 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1003 | void Layer::commitTransaction() { | 
 | 1004 |     mDrawingState = mCurrentState; | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1005 | } | 
 | 1006 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1007 | uint32_t Layer::getTransactionFlags(uint32_t flags) { | 
 | 1008 |     return android_atomic_and(~flags, &mTransactionFlags) & flags; | 
 | 1009 | } | 
 | 1010 |  | 
 | 1011 | uint32_t Layer::setTransactionFlags(uint32_t flags) { | 
 | 1012 |     return android_atomic_or(flags, &mTransactionFlags); | 
 | 1013 | } | 
 | 1014 |  | 
 | 1015 | bool Layer::setPosition(float x, float y) { | 
 | 1016 |     if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) | 
 | 1017 |         return false; | 
 | 1018 |     mCurrentState.sequence++; | 
 | 1019 |     mCurrentState.transform.set(x, y); | 
 | 1020 |     setTransactionFlags(eTransactionNeeded); | 
 | 1021 |     return true; | 
 | 1022 | } | 
 | 1023 | bool Layer::setLayer(uint32_t z) { | 
 | 1024 |     if (mCurrentState.z == z) | 
 | 1025 |         return false; | 
 | 1026 |     mCurrentState.sequence++; | 
 | 1027 |     mCurrentState.z = z; | 
 | 1028 |     setTransactionFlags(eTransactionNeeded); | 
 | 1029 |     return true; | 
 | 1030 | } | 
 | 1031 | bool Layer::setSize(uint32_t w, uint32_t h) { | 
 | 1032 |     if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) | 
 | 1033 |         return false; | 
 | 1034 |     mCurrentState.requested.w = w; | 
 | 1035 |     mCurrentState.requested.h = h; | 
 | 1036 |     setTransactionFlags(eTransactionNeeded); | 
 | 1037 |     return true; | 
 | 1038 | } | 
 | 1039 | bool Layer::setAlpha(uint8_t alpha) { | 
 | 1040 |     if (mCurrentState.alpha == alpha) | 
 | 1041 |         return false; | 
 | 1042 |     mCurrentState.sequence++; | 
 | 1043 |     mCurrentState.alpha = alpha; | 
 | 1044 |     setTransactionFlags(eTransactionNeeded); | 
 | 1045 |     return true; | 
 | 1046 | } | 
 | 1047 | bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { | 
 | 1048 |     mCurrentState.sequence++; | 
 | 1049 |     mCurrentState.transform.set( | 
 | 1050 |             matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy); | 
 | 1051 |     setTransactionFlags(eTransactionNeeded); | 
 | 1052 |     return true; | 
 | 1053 | } | 
 | 1054 | bool Layer::setTransparentRegionHint(const Region& transparent) { | 
| Mathias Agopian | 2ca7939 | 2013-04-02 18:30:32 -0700 | [diff] [blame] | 1055 |     mCurrentState.requestedTransparentRegion = transparent; | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1056 |     setTransactionFlags(eTransactionNeeded); | 
 | 1057 |     return true; | 
 | 1058 | } | 
 | 1059 | bool Layer::setFlags(uint8_t flags, uint8_t mask) { | 
 | 1060 |     const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); | 
 | 1061 |     if (mCurrentState.flags == newFlags) | 
 | 1062 |         return false; | 
 | 1063 |     mCurrentState.sequence++; | 
 | 1064 |     mCurrentState.flags = newFlags; | 
 | 1065 |     setTransactionFlags(eTransactionNeeded); | 
 | 1066 |     return true; | 
 | 1067 | } | 
 | 1068 | bool Layer::setCrop(const Rect& crop) { | 
 | 1069 |     if (mCurrentState.requested.crop == crop) | 
 | 1070 |         return false; | 
 | 1071 |     mCurrentState.sequence++; | 
 | 1072 |     mCurrentState.requested.crop = crop; | 
 | 1073 |     setTransactionFlags(eTransactionNeeded); | 
 | 1074 |     return true; | 
 | 1075 | } | 
 | 1076 |  | 
 | 1077 | bool Layer::setLayerStack(uint32_t layerStack) { | 
 | 1078 |     if (mCurrentState.layerStack == layerStack) | 
 | 1079 |         return false; | 
 | 1080 |     mCurrentState.sequence++; | 
 | 1081 |     mCurrentState.layerStack = layerStack; | 
 | 1082 |     setTransactionFlags(eTransactionNeeded); | 
 | 1083 |     return true; | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1084 | } | 
 | 1085 |  | 
| Dan Stoza | ee44edd | 2015-03-23 15:50:23 -0700 | [diff] [blame] | 1086 | void Layer::useSurfaceDamage() { | 
 | 1087 |     if (mFlinger->mForceFullDamage) { | 
 | 1088 |         surfaceDamageRegion = Region::INVALID_REGION; | 
 | 1089 |     } else { | 
 | 1090 |         surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage(); | 
 | 1091 |     } | 
 | 1092 | } | 
 | 1093 |  | 
 | 1094 | void Layer::useEmptyDamage() { | 
 | 1095 |     surfaceDamageRegion.clear(); | 
 | 1096 | } | 
 | 1097 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1098 | // ---------------------------------------------------------------------------- | 
 | 1099 | // pageflip handling... | 
 | 1100 | // ---------------------------------------------------------------------------- | 
 | 1101 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1102 | bool Layer::shouldPresentNow(const DispSync& dispSync) const { | 
| Dan Stoza | d87defa | 2015-07-29 16:15:50 -0700 | [diff] [blame] | 1103 |     if (mSidebandStreamChanged) { | 
 | 1104 |         return true; | 
 | 1105 |     } | 
 | 1106 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1107 |     Mutex::Autolock lock(mQueueItemLock); | 
| Dan Stoza | 0eb2d39 | 2015-07-06 12:56:50 -0700 | [diff] [blame] | 1108 |     if (mQueueItems.empty()) { | 
 | 1109 |         return false; | 
 | 1110 |     } | 
 | 1111 |     auto timestamp = mQueueItems[0].mTimestamp; | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1112 |     nsecs_t expectedPresent = | 
 | 1113 |             mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); | 
| Dan Stoza | 0eb2d39 | 2015-07-06 12:56:50 -0700 | [diff] [blame] | 1114 |  | 
 | 1115 |     // Ignore timestamps more than a second in the future | 
 | 1116 |     bool isPlausible = timestamp < (expectedPresent + s2ns(1)); | 
 | 1117 |     ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " | 
 | 1118 |             "relative to expectedPresent %" PRId64, mName.string(), timestamp, | 
 | 1119 |             expectedPresent); | 
 | 1120 |  | 
 | 1121 |     bool isDue = timestamp < expectedPresent; | 
 | 1122 |     return isDue || !isPlausible; | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1123 | } | 
 | 1124 |  | 
| Mathias Agopian | 4d143ee | 2012-02-23 20:05:39 -0800 | [diff] [blame] | 1125 | bool Layer::onPreComposition() { | 
 | 1126 |     mRefreshPending = false; | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 1127 |     return mQueuedFrames > 0 || mSidebandStreamChanged; | 
| Mathias Agopian | 99ce5cd | 2012-01-31 18:24:27 -0800 | [diff] [blame] | 1128 | } | 
 | 1129 |  | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 1130 | void Layer::onPostComposition() { | 
 | 1131 |     if (mFrameLatencyNeeded) { | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 1132 |         nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); | 
| Jamie Gennis | 82dbc74 | 2012-11-08 19:23:28 -0800 | [diff] [blame] | 1133 |         mFrameTracker.setDesiredPresentTime(desiredPresentTime); | 
 | 1134 |  | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 1135 |         sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence(); | 
| Jamie Gennis | 789a6c3 | 2013-02-25 13:37:54 -0800 | [diff] [blame] | 1136 |         if (frameReadyFence->isValid()) { | 
| Jamie Gennis | 82dbc74 | 2012-11-08 19:23:28 -0800 | [diff] [blame] | 1137 |             mFrameTracker.setFrameReadyFence(frameReadyFence); | 
 | 1138 |         } else { | 
 | 1139 |             // There was no fence for this frame, so assume that it was ready | 
 | 1140 |             // to be presented at the desired present time. | 
 | 1141 |             mFrameTracker.setFrameReadyTime(desiredPresentTime); | 
 | 1142 |         } | 
 | 1143 |  | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 1144 |         const HWComposer& hwc = mFlinger->getHwComposer(); | 
| Jamie Gennis | 82dbc74 | 2012-11-08 19:23:28 -0800 | [diff] [blame] | 1145 |         sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); | 
| Jamie Gennis | 789a6c3 | 2013-02-25 13:37:54 -0800 | [diff] [blame] | 1146 |         if (presentFence->isValid()) { | 
| Jamie Gennis | 82dbc74 | 2012-11-08 19:23:28 -0800 | [diff] [blame] | 1147 |             mFrameTracker.setActualPresentFence(presentFence); | 
 | 1148 |         } else { | 
 | 1149 |             // The HWC doesn't support present fences, so use the refresh | 
 | 1150 |             // timestamp instead. | 
 | 1151 |             nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); | 
 | 1152 |             mFrameTracker.setActualPresentTime(presentTime); | 
 | 1153 |         } | 
 | 1154 |  | 
 | 1155 |         mFrameTracker.advanceFrame(); | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 1156 |         mFrameLatencyNeeded = false; | 
 | 1157 |     } | 
 | 1158 | } | 
 | 1159 |  | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 1160 | bool Layer::isVisible() const { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1161 |     const Layer::State& s(mDrawingState); | 
 | 1162 |     return !(s.flags & layer_state_t::eLayerHidden) && s.alpha | 
| Wonsik Kim | afe3081 | 2014-03-31 23:16:08 +0900 | [diff] [blame] | 1163 |             && (mActiveBuffer != NULL || mSidebandStream != NULL); | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 1164 | } | 
 | 1165 |  | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1166 | Region Layer::latchBuffer(bool& recomputeVisibleRegions) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1167 | { | 
| Jamie Gennis | 1c8e95c | 2012-02-23 19:27:23 -0800 | [diff] [blame] | 1168 |     ATRACE_CALL(); | 
 | 1169 |  | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 1170 |     if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { | 
 | 1171 |         // mSidebandStreamChanged was true | 
 | 1172 |         mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); | 
| Dan Stoza | 12e0a27 | 2015-05-05 14:00:52 -0700 | [diff] [blame] | 1173 |         if (mSidebandStream != NULL) { | 
 | 1174 |             setTransactionFlags(eTransactionNeeded); | 
 | 1175 |             mFlinger->setTransactionFlags(eTraversalNeeded); | 
 | 1176 |         } | 
| Jesse Hall | 5bf786d | 2014-09-30 10:35:11 -0700 | [diff] [blame] | 1177 |         recomputeVisibleRegions = true; | 
 | 1178 |  | 
 | 1179 |         const State& s(getDrawingState()); | 
 | 1180 |         return s.transform.transform(Region(Rect(s.active.w, s.active.h))); | 
| Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 1181 |     } | 
 | 1182 |  | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1183 |     Region outDirtyRegion; | 
| Jamie Gennis | 3d8063b | 2011-06-26 18:27:47 -0700 | [diff] [blame] | 1184 |     if (mQueuedFrames > 0) { | 
| Mathias Agopian | 99ce5cd | 2012-01-31 18:24:27 -0800 | [diff] [blame] | 1185 |  | 
 | 1186 |         // if we've already called updateTexImage() without going through | 
 | 1187 |         // a composition step, we have to skip this layer at this point | 
 | 1188 |         // because we cannot call updateTeximage() without a corresponding | 
 | 1189 |         // compositionComplete() call. | 
 | 1190 |         // we'll trigger an update in onPreComposition(). | 
| Mathias Agopian | 4d143ee | 2012-02-23 20:05:39 -0800 | [diff] [blame] | 1191 |         if (mRefreshPending) { | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1192 |             return outDirtyRegion; | 
| Mathias Agopian | 99ce5cd | 2012-01-31 18:24:27 -0800 | [diff] [blame] | 1193 |         } | 
 | 1194 |  | 
| Jamie Gennis | 351a513 | 2011-09-14 18:23:37 -0700 | [diff] [blame] | 1195 |         // Capture the old state of the layer for comparisons later | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 1196 |         const State& s(getDrawingState()); | 
 | 1197 |         const bool oldOpacity = isOpaque(s); | 
| Jamie Gennis | 351a513 | 2011-09-14 18:23:37 -0700 | [diff] [blame] | 1198 |         sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; | 
| Jamie Gennis | db5230f | 2011-07-28 14:54:07 -0700 | [diff] [blame] | 1199 |  | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 1200 |         struct Reject : public SurfaceFlingerConsumer::BufferRejecter { | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1201 |             Layer::State& front; | 
 | 1202 |             Layer::State& current; | 
 | 1203 |             bool& recomputeVisibleRegions; | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 1204 |             bool stickyTransformSet; | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1205 |             Reject(Layer::State& front, Layer::State& current, | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 1206 |                     bool& recomputeVisibleRegions, bool stickySet) | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1207 |                 : front(front), current(current), | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 1208 |                   recomputeVisibleRegions(recomputeVisibleRegions), | 
 | 1209 |                   stickyTransformSet(stickySet) { | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1210 |             } | 
 | 1211 |  | 
 | 1212 |             virtual bool reject(const sp<GraphicBuffer>& buf, | 
| Dan Stoza | 11611f9 | 2015-03-12 15:12:44 -0700 | [diff] [blame] | 1213 |                     const BufferItem& item) { | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1214 |                 if (buf == NULL) { | 
 | 1215 |                     return false; | 
 | 1216 |                 } | 
 | 1217 |  | 
 | 1218 |                 uint32_t bufWidth  = buf->getWidth(); | 
 | 1219 |                 uint32_t bufHeight = buf->getHeight(); | 
 | 1220 |  | 
 | 1221 |                 // check that we received a buffer of the right size | 
 | 1222 |                 // (Take the buffer's orientation into account) | 
 | 1223 |                 if (item.mTransform & Transform::ROT_90) { | 
 | 1224 |                     swap(bufWidth, bufHeight); | 
 | 1225 |                 } | 
 | 1226 |  | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1227 |                 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; | 
 | 1228 |                 if (front.active != front.requested) { | 
 | 1229 |  | 
 | 1230 |                     if (isFixedSize || | 
 | 1231 |                             (bufWidth == front.requested.w && | 
 | 1232 |                              bufHeight == front.requested.h)) | 
 | 1233 |                     { | 
 | 1234 |                         // Here we pretend the transaction happened by updating the | 
 | 1235 |                         // current and drawing states. Drawing state is only accessed | 
 | 1236 |                         // in this thread, no need to have it locked | 
 | 1237 |                         front.active = front.requested; | 
 | 1238 |  | 
 | 1239 |                         // We also need to update the current state so that | 
 | 1240 |                         // we don't end-up overwriting the drawing state with | 
 | 1241 |                         // this stale current state during the next transaction | 
 | 1242 |                         // | 
 | 1243 |                         // NOTE: We don't need to hold the transaction lock here | 
 | 1244 |                         // because State::active is only accessed from this thread. | 
 | 1245 |                         current.active = front.active; | 
 | 1246 |  | 
 | 1247 |                         // recompute visible region | 
 | 1248 |                         recomputeVisibleRegions = true; | 
 | 1249 |                     } | 
 | 1250 |  | 
 | 1251 |                     ALOGD_IF(DEBUG_RESIZE, | 
| Andy McFadden | 6905205 | 2012-09-14 16:10:11 -0700 | [diff] [blame] | 1252 |                             "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1253 |                             "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" | 
 | 1254 |                             "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n", | 
| Andy McFadden | 6905205 | 2012-09-14 16:10:11 -0700 | [diff] [blame] | 1255 |                             bufWidth, bufHeight, item.mTransform, item.mScalingMode, | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1256 |                             front.active.w, front.active.h, | 
 | 1257 |                             front.active.crop.left, | 
 | 1258 |                             front.active.crop.top, | 
 | 1259 |                             front.active.crop.right, | 
 | 1260 |                             front.active.crop.bottom, | 
 | 1261 |                             front.active.crop.getWidth(), | 
 | 1262 |                             front.active.crop.getHeight(), | 
 | 1263 |                             front.requested.w, front.requested.h, | 
 | 1264 |                             front.requested.crop.left, | 
 | 1265 |                             front.requested.crop.top, | 
 | 1266 |                             front.requested.crop.right, | 
 | 1267 |                             front.requested.crop.bottom, | 
 | 1268 |                             front.requested.crop.getWidth(), | 
 | 1269 |                             front.requested.crop.getHeight()); | 
 | 1270 |                 } | 
 | 1271 |  | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 1272 |                 if (!isFixedSize && !stickyTransformSet) { | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1273 |                     if (front.active.w != bufWidth || | 
 | 1274 |                         front.active.h != bufHeight) { | 
| Mathias Agopian | 4824d40 | 2012-06-04 18:16:30 -0700 | [diff] [blame] | 1275 |                         // reject this buffer | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 1276 |                         ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}", | 
 | 1277 |                                 bufWidth, bufHeight, front.active.w, front.active.h); | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1278 |                         return true; | 
 | 1279 |                     } | 
 | 1280 |                 } | 
| Mathias Agopian | 2ca7939 | 2013-04-02 18:30:32 -0700 | [diff] [blame] | 1281 |  | 
 | 1282 |                 // if the transparent region has changed (this test is | 
 | 1283 |                 // conservative, but that's fine, worst case we're doing | 
 | 1284 |                 // a bit of extra work), we latch the new one and we | 
 | 1285 |                 // trigger a visible-region recompute. | 
 | 1286 |                 if (!front.activeTransparentRegion.isTriviallyEqual( | 
 | 1287 |                         front.requestedTransparentRegion)) { | 
 | 1288 |                     front.activeTransparentRegion = front.requestedTransparentRegion; | 
| Mathias Agopian | 6c67f0f | 2013-04-12 16:58:11 -0700 | [diff] [blame] | 1289 |  | 
 | 1290 |                     // We also need to update the current state so that | 
 | 1291 |                     // we don't end-up overwriting the drawing state with | 
 | 1292 |                     // this stale current state during the next transaction | 
 | 1293 |                     // | 
 | 1294 |                     // NOTE: We don't need to hold the transaction lock here | 
 | 1295 |                     // because State::active is only accessed from this thread. | 
 | 1296 |                     current.activeTransparentRegion = front.activeTransparentRegion; | 
 | 1297 |  | 
 | 1298 |                     // recompute visible region | 
| Mathias Agopian | 2ca7939 | 2013-04-02 18:30:32 -0700 | [diff] [blame] | 1299 |                     recomputeVisibleRegions = true; | 
 | 1300 |                 } | 
 | 1301 |  | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1302 |                 return false; | 
 | 1303 |             } | 
 | 1304 |         }; | 
 | 1305 |  | 
| Ruben Brunk | 1681d95 | 2014-06-27 15:51:55 -0700 | [diff] [blame] | 1306 |         Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions, | 
 | 1307 |                 getProducerStickyTransform() != 0); | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1308 |  | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 1309 |         uint64_t maxFrameNumber = 0; | 
 | 1310 |         { | 
 | 1311 |             Mutex::Autolock lock(mQueueItemLock); | 
 | 1312 |             maxFrameNumber = mLastFrameNumberReceived; | 
 | 1313 |         } | 
 | 1314 |  | 
| Andy McFadden | 41d67d7 | 2014-04-25 16:58:34 -0700 | [diff] [blame] | 1315 |         status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r, | 
| Dan Stoza | a4650a5 | 2015-05-12 12:56:16 -0700 | [diff] [blame] | 1316 |                 mFlinger->mPrimaryDispSync, maxFrameNumber); | 
| Andy McFadden | 1585c4d | 2013-06-28 13:52:40 -0700 | [diff] [blame] | 1317 |         if (updateResult == BufferQueue::PRESENT_LATER) { | 
 | 1318 |             // Producer doesn't want buffer to be displayed yet.  Signal a | 
 | 1319 |             // layer update so we check again at the next opportunity. | 
 | 1320 |             mFlinger->signalLayerUpdate(); | 
 | 1321 |             return outDirtyRegion; | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 1322 |         } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { | 
 | 1323 |             // If the buffer has been rejected, remove it from the shadow queue | 
 | 1324 |             // and return early | 
 | 1325 |             Mutex::Autolock lock(mQueueItemLock); | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 1326 |             mQueueItems.removeAt(0); | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 1327 |             android_atomic_dec(&mQueuedFrames); | 
 | 1328 |             return outDirtyRegion; | 
| Dan Stoza | 65476f3 | 2015-05-14 09:27:25 -0700 | [diff] [blame] | 1329 |         } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { | 
 | 1330 |             // This can occur if something goes wrong when trying to create the | 
 | 1331 |             // EGLImage for this buffer. If this happens, the buffer has already | 
 | 1332 |             // been released, so we need to clean up the queue and bug out | 
 | 1333 |             // early. | 
 | 1334 |             { | 
 | 1335 |                 Mutex::Autolock lock(mQueueItemLock); | 
 | 1336 |                 mQueueItems.clear(); | 
 | 1337 |                 android_atomic_and(0, &mQueuedFrames); | 
 | 1338 |             } | 
 | 1339 |  | 
 | 1340 |             // Once we have hit this state, the shadow queue may no longer | 
 | 1341 |             // correctly reflect the incoming BufferQueue's contents, so even if | 
 | 1342 |             // updateTexImage starts working, the only safe course of action is | 
 | 1343 |             // to continue to ignore updates. | 
 | 1344 |             mUpdateTexImageFailed = true; | 
 | 1345 |  | 
 | 1346 |             return outDirtyRegion; | 
| Andy McFadden | 1585c4d | 2013-06-28 13:52:40 -0700 | [diff] [blame] | 1347 |         } | 
 | 1348 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1349 |         { // Autolock scope | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 1350 |             auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); | 
 | 1351 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1352 |             Mutex::Autolock lock(mQueueItemLock); | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 1353 |  | 
 | 1354 |             // Remove any stale buffers that have been dropped during | 
 | 1355 |             // updateTexImage | 
 | 1356 |             while (mQueueItems[0].mFrameNumber != currentFrameNumber) { | 
 | 1357 |                 mQueueItems.removeAt(0); | 
 | 1358 |                 android_atomic_dec(&mQueuedFrames); | 
 | 1359 |             } | 
 | 1360 |  | 
| Dan Stoza | 6b9454d | 2014-11-07 16:00:59 -0800 | [diff] [blame] | 1361 |             mQueueItems.removeAt(0); | 
 | 1362 |         } | 
 | 1363 |  | 
| Dan Stoza | ecc5040 | 2015-04-28 14:42:06 -0700 | [diff] [blame] | 1364 |  | 
| Andy McFadden | 1585c4d | 2013-06-28 13:52:40 -0700 | [diff] [blame] | 1365 |         // Decrement the queued-frames count.  Signal another event if we | 
 | 1366 |         // have more frames pending. | 
 | 1367 |         if (android_atomic_dec(&mQueuedFrames) > 1) { | 
 | 1368 |             mFlinger->signalLayerUpdate(); | 
 | 1369 |         } | 
 | 1370 |  | 
 | 1371 |         if (updateResult != NO_ERROR) { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1372 |             // something happened! | 
 | 1373 |             recomputeVisibleRegions = true; | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1374 |             return outDirtyRegion; | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1375 |         } | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1376 |  | 
| Jamie Gennis | 351a513 | 2011-09-14 18:23:37 -0700 | [diff] [blame] | 1377 |         // update the active buffer | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 1378 |         mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(); | 
| Mathias Agopian | e31564d | 2012-05-29 20:41:03 -0700 | [diff] [blame] | 1379 |         if (mActiveBuffer == NULL) { | 
 | 1380 |             // this can only happen if the very first buffer was rejected. | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1381 |             return outDirtyRegion; | 
| Mathias Agopian | e31564d | 2012-05-29 20:41:03 -0700 | [diff] [blame] | 1382 |         } | 
| Mathias Agopian | da9584d | 2010-12-13 18:51:59 -0800 | [diff] [blame] | 1383 |  | 
| Mathias Agopian | 4824d40 | 2012-06-04 18:16:30 -0700 | [diff] [blame] | 1384 |         mRefreshPending = true; | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1385 |         mFrameLatencyNeeded = true; | 
| Mathias Agopian | e31564d | 2012-05-29 20:41:03 -0700 | [diff] [blame] | 1386 |         if (oldActiveBuffer == NULL) { | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1387 |              // the first time we receive a buffer, we need to trigger a | 
 | 1388 |              // geometry invalidation. | 
| Andy McFadden | ab10c58 | 2012-09-26 16:19:12 -0700 | [diff] [blame] | 1389 |             recomputeVisibleRegions = true; | 
| Mathias Agopian | 2c8207e | 2012-05-23 17:56:42 -0700 | [diff] [blame] | 1390 |          } | 
 | 1391 |  | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 1392 |         Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); | 
 | 1393 |         const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); | 
 | 1394 |         const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); | 
| Mathias Agopian | 702634a | 2012-05-23 17:50:31 -0700 | [diff] [blame] | 1395 |         if ((crop != mCurrentCrop) || | 
 | 1396 |             (transform != mCurrentTransform) || | 
 | 1397 |             (scalingMode != mCurrentScalingMode)) | 
 | 1398 |         { | 
 | 1399 |             mCurrentCrop = crop; | 
 | 1400 |             mCurrentTransform = transform; | 
 | 1401 |             mCurrentScalingMode = scalingMode; | 
| Andy McFadden | ab10c58 | 2012-09-26 16:19:12 -0700 | [diff] [blame] | 1402 |             recomputeVisibleRegions = true; | 
| Mathias Agopian | 702634a | 2012-05-23 17:50:31 -0700 | [diff] [blame] | 1403 |         } | 
 | 1404 |  | 
 | 1405 |         if (oldActiveBuffer != NULL) { | 
| Mathias Agopian | e31564d | 2012-05-29 20:41:03 -0700 | [diff] [blame] | 1406 |             uint32_t bufWidth  = mActiveBuffer->getWidth(); | 
 | 1407 |             uint32_t bufHeight = mActiveBuffer->getHeight(); | 
| Mathias Agopian | 702634a | 2012-05-23 17:50:31 -0700 | [diff] [blame] | 1408 |             if (bufWidth != uint32_t(oldActiveBuffer->width) || | 
 | 1409 |                 bufHeight != uint32_t(oldActiveBuffer->height)) { | 
| Andy McFadden | ab10c58 | 2012-09-26 16:19:12 -0700 | [diff] [blame] | 1410 |                 recomputeVisibleRegions = true; | 
| Mathias Agopian | 702634a | 2012-05-23 17:50:31 -0700 | [diff] [blame] | 1411 |             } | 
 | 1412 |         } | 
 | 1413 |  | 
 | 1414 |         mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 1415 |         if (oldOpacity != isOpaque(s)) { | 
| Mathias Agopian | 702634a | 2012-05-23 17:50:31 -0700 | [diff] [blame] | 1416 |             recomputeVisibleRegions = true; | 
 | 1417 |         } | 
 | 1418 |  | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1419 |         // FIXME: postedRegion should be dirty & bounds | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 1420 |         Region dirtyRegion(Rect(s.active.w, s.active.h)); | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1421 |  | 
 | 1422 |         // transform the dirty region to window-manager space | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 1423 |         outDirtyRegion = (s.transform.transform(dirtyRegion)); | 
| Mathias Agopian | caa600c | 2009-09-16 18:27:24 -0700 | [diff] [blame] | 1424 |     } | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1425 |     return outDirtyRegion; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1426 | } | 
 | 1427 |  | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1428 | uint32_t Layer::getEffectiveUsage(uint32_t usage) const | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1429 | { | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1430 |     // TODO: should we do something special if mSecure is set? | 
 | 1431 |     if (mProtectedByApp) { | 
 | 1432 |         // need a hardware-protected path to external video sink | 
 | 1433 |         usage |= GraphicBuffer::USAGE_PROTECTED; | 
| Jamie Gennis | 54cc83e | 2010-11-02 11:51:32 -0700 | [diff] [blame] | 1434 |     } | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 1435 |     if (mPotentialCursor) { | 
 | 1436 |         usage |= GraphicBuffer::USAGE_CURSOR; | 
 | 1437 |     } | 
| Jamie Gennis | 3599bf2 | 2011-08-10 11:48:07 -0700 | [diff] [blame] | 1438 |     usage |= GraphicBuffer::USAGE_HW_COMPOSER; | 
| Mathias Agopian | a67932f | 2011-04-20 14:20:59 -0700 | [diff] [blame] | 1439 |     return usage; | 
| Mathias Agopian | b5b7f26 | 2010-05-07 15:58:44 -0700 | [diff] [blame] | 1440 | } | 
 | 1441 |  | 
| Mathias Agopian | 8430095 | 2012-11-21 16:02:13 -0800 | [diff] [blame] | 1442 | void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { | 
| Mathias Agopian | a458364 | 2011-08-23 18:03:18 -0700 | [diff] [blame] | 1443 |     uint32_t orientation = 0; | 
 | 1444 |     if (!mFlinger->mDebugDisableTransformHint) { | 
| Mathias Agopian | 8430095 | 2012-11-21 16:02:13 -0800 | [diff] [blame] | 1445 |         // The transform hint is used to improve performance, but we can | 
 | 1446 |         // only have a single transform hint, it cannot | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1447 |         // apply to all displays. | 
| Mathias Agopian | 4297734 | 2012-08-05 00:40:46 -0700 | [diff] [blame] | 1448 |         const Transform& planeTransform(hw->getTransform()); | 
| Mathias Agopian | 4fec873 | 2012-06-29 14:12:52 -0700 | [diff] [blame] | 1449 |         orientation = planeTransform.getOrientation(); | 
| Mathias Agopian | a458364 | 2011-08-23 18:03:18 -0700 | [diff] [blame] | 1450 |         if (orientation & Transform::ROT_INVALID) { | 
 | 1451 |             orientation = 0; | 
 | 1452 |         } | 
 | 1453 |     } | 
| Andy McFadden | bf974ab | 2012-12-04 16:51:15 -0800 | [diff] [blame] | 1454 |     mSurfaceFlingerConsumer->setTransformHint(orientation); | 
| Mathias Agopian | a458364 | 2011-08-23 18:03:18 -0700 | [diff] [blame] | 1455 | } | 
 | 1456 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1457 | // ---------------------------------------------------------------------------- | 
 | 1458 | // debugging | 
 | 1459 | // ---------------------------------------------------------------------------- | 
 | 1460 |  | 
| Mathias Agopian | 3e25fd8 | 2013-04-22 17:52:16 +0200 | [diff] [blame] | 1461 | void Layer::dump(String8& result, Colorizer& colorizer) const | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1462 | { | 
| Mathias Agopian | 1eae0ee | 2013-06-05 16:59:15 -0700 | [diff] [blame] | 1463 |     const Layer::State& s(getDrawingState()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1464 |  | 
| Mathias Agopian | 3e25fd8 | 2013-04-22 17:52:16 +0200 | [diff] [blame] | 1465 |     colorizer.colorize(result, Colorizer::GREEN); | 
| Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 1466 |     result.appendFormat( | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1467 |             "+ %s %p (%s)\n", | 
 | 1468 |             getTypeId(), this, getName().string()); | 
| Mathias Agopian | 3e25fd8 | 2013-04-22 17:52:16 +0200 | [diff] [blame] | 1469 |     colorizer.reset(result); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1470 |  | 
| Mathias Agopian | 2ca7939 | 2013-04-02 18:30:32 -0700 | [diff] [blame] | 1471 |     s.activeTransparentRegion.dump(result, "transparentRegion"); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1472 |     visibleRegion.dump(result, "visibleRegion"); | 
| Dan Stoza | ee44edd | 2015-03-23 15:50:23 -0700 | [diff] [blame] | 1473 |     surfaceDamageRegion.dump(result, "surfaceDamageRegion"); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1474 |     sp<Client> client(mClientRef.promote()); | 
 | 1475 |  | 
| Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 1476 |     result.appendFormat(            "      " | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1477 |             "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " | 
 | 1478 |             "isOpaque=%1d, invalidate=%1d, " | 
 | 1479 |             "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n" | 
 | 1480 |             "      client=%p\n", | 
 | 1481 |             s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, | 
 | 1482 |             s.active.crop.left, s.active.crop.top, | 
 | 1483 |             s.active.crop.right, s.active.crop.bottom, | 
| Andy McFadden | 4125a4f | 2014-01-29 17:17:11 -0800 | [diff] [blame] | 1484 |             isOpaque(s), contentDirty, | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1485 |             s.alpha, s.flags, | 
 | 1486 |             s.transform[0][0], s.transform[0][1], | 
 | 1487 |             s.transform[1][0], s.transform[1][1], | 
 | 1488 |             client.get()); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1489 |  | 
 | 1490 |     sp<const GraphicBuffer> buf0(mActiveBuffer); | 
 | 1491 |     uint32_t w0=0, h0=0, s0=0, f0=0; | 
 | 1492 |     if (buf0 != 0) { | 
 | 1493 |         w0 = buf0->getWidth(); | 
 | 1494 |         h0 = buf0->getHeight(); | 
 | 1495 |         s0 = buf0->getStride(); | 
 | 1496 |         f0 = buf0->format; | 
 | 1497 |     } | 
| Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 1498 |     result.appendFormat( | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1499 |             "      " | 
 | 1500 |             "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X]," | 
 | 1501 |             " queued-frames=%d, mRefreshPending=%d\n", | 
 | 1502 |             mFormat, w0, h0, s0,f0, | 
 | 1503 |             mQueuedFrames, mRefreshPending); | 
 | 1504 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1505 |     if (mSurfaceFlingerConsumer != 0) { | 
| Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 1506 |         mSurfaceFlingerConsumer->dump(result, "            "); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1507 |     } | 
 | 1508 | } | 
 | 1509 |  | 
| Svetoslav | d85084b | 2014-03-20 10:28:31 -0700 | [diff] [blame] | 1510 | void Layer::dumpFrameStats(String8& result) const { | 
 | 1511 |     mFrameTracker.dumpStats(result); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1512 | } | 
 | 1513 |  | 
| Svetoslav | d85084b | 2014-03-20 10:28:31 -0700 | [diff] [blame] | 1514 | void Layer::clearFrameStats() { | 
 | 1515 |     mFrameTracker.clearStats(); | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1516 | } | 
 | 1517 |  | 
| Jamie Gennis | 6547ff4 | 2013-07-16 20:12:42 -0700 | [diff] [blame] | 1518 | void Layer::logFrameStats() { | 
 | 1519 |     mFrameTracker.logAndResetStats(mName); | 
 | 1520 | } | 
 | 1521 |  | 
| Svetoslav | d85084b | 2014-03-20 10:28:31 -0700 | [diff] [blame] | 1522 | void Layer::getFrameStats(FrameStats* outStats) const { | 
 | 1523 |     mFrameTracker.getStats(outStats); | 
 | 1524 | } | 
 | 1525 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 1526 | // --------------------------------------------------------------------------- | 
 | 1527 |  | 
 | 1528 | Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, | 
 | 1529 |         const sp<Layer>& layer) | 
 | 1530 |     : mFlinger(flinger), mLayer(layer) { | 
 | 1531 | } | 
 | 1532 |  | 
 | 1533 | Layer::LayerCleaner::~LayerCleaner() { | 
 | 1534 |     // destroy client resources | 
 | 1535 |     mFlinger->onLayerDestroyed(mLayer); | 
 | 1536 | } | 
 | 1537 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1538 | // --------------------------------------------------------------------------- | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1539 | }; // namespace android | 
| Mathias Agopian | 3f84483 | 2013-08-07 21:24:32 -0700 | [diff] [blame] | 1540 |  | 
 | 1541 | #if defined(__gl_h_) | 
 | 1542 | #error "don't include gl/gl.h in this file" | 
 | 1543 | #endif | 
 | 1544 |  | 
 | 1545 | #if defined(__gl2_h_) | 
 | 1546 | #error "don't include gl2/gl2.h in this file" | 
 | 1547 | #endif |