| 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 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 17 | #include <stdlib.h> | 
 | 18 | #include <stdio.h> | 
 | 19 | #include <stdint.h> | 
 | 20 | #include <unistd.h> | 
 | 21 | #include <fcntl.h> | 
 | 22 | #include <errno.h> | 
 | 23 | #include <math.h> | 
| Jean-Baptiste Queru | a837ba7 | 2009-01-26 11:51:12 -0800 | [diff] [blame] | 24 | #include <limits.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 25 | #include <sys/types.h> | 
 | 26 | #include <sys/stat.h> | 
 | 27 | #include <sys/ioctl.h> | 
 | 28 |  | 
 | 29 | #include <cutils/log.h> | 
 | 30 | #include <cutils/properties.h> | 
 | 31 |  | 
| Mathias Agopian | c5b2c0b | 2009-05-19 19:08:10 -0700 | [diff] [blame] | 32 | #include <binder/IPCThreadState.h> | 
 | 33 | #include <binder/IServiceManager.h> | 
| Mathias Agopian | 7303c6b | 2009-07-02 18:11:53 -0700 | [diff] [blame] | 34 | #include <binder/MemoryHeapBase.h> | 
 | 35 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 36 | #include <utils/String8.h> | 
 | 37 | #include <utils/String16.h> | 
 | 38 | #include <utils/StopWatch.h> | 
 | 39 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 40 | #include <ui/GraphicBufferAllocator.h> | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 41 | #include <ui/GraphicLog.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 42 | #include <ui/PixelFormat.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 43 |  | 
 | 44 | #include <pixelflinger/pixelflinger.h> | 
 | 45 | #include <GLES/gl.h> | 
 | 46 |  | 
 | 47 | #include "clz.h" | 
| Mathias Agopian | 1f7bec6 | 2010-06-25 18:02:21 -0700 | [diff] [blame] | 48 | #include "GLExtensions.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 49 | #include "Layer.h" | 
 | 50 | #include "LayerBlur.h" | 
 | 51 | #include "LayerBuffer.h" | 
 | 52 | #include "LayerDim.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 53 | #include "SurfaceFlinger.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 54 |  | 
 | 55 | #include "DisplayHardware/DisplayHardware.h" | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 56 |  | 
| Mathias Agopian | a1ecca9 | 2009-05-21 19:21:59 -0700 | [diff] [blame] | 57 | /* ideally AID_GRAPHICS would be in a semi-public header | 
 | 58 |  * or there would be a way to map a user/group name to its id | 
 | 59 |  */ | 
 | 60 | #ifndef AID_GRAPHICS | 
 | 61 | #define AID_GRAPHICS 1003 | 
 | 62 | #endif | 
 | 63 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 64 | #define DISPLAY_COUNT       1 | 
 | 65 |  | 
 | 66 | namespace android { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 67 | // --------------------------------------------------------------------------- | 
 | 68 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 69 | SurfaceFlinger::SurfaceFlinger() | 
 | 70 |     :   BnSurfaceComposer(), Thread(false), | 
 | 71 |         mTransactionFlags(0), | 
 | 72 |         mTransactionCount(0), | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 73 |         mResizeTransationPending(false), | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 74 |         mLayersRemoved(false), | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 75 |         mBootTime(systemTime()), | 
| Mathias Agopian | 375f563 | 2009-06-15 18:24:59 -0700 | [diff] [blame] | 76 |         mHardwareTest("android.permission.HARDWARE_TEST"), | 
 | 77 |         mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"), | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 78 |         mReadFramebuffer("android.permission.READ_FRAME_BUFFER"), | 
| Mathias Agopian | 375f563 | 2009-06-15 18:24:59 -0700 | [diff] [blame] | 79 |         mDump("android.permission.DUMP"), | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 80 |         mVisibleRegionsDirty(false), | 
 | 81 |         mDeferReleaseConsole(false), | 
 | 82 |         mFreezeDisplay(false), | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 83 |         mElectronBeamAnimationMode(0), | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 84 |         mFreezeCount(0), | 
| The Android Open Source Project | bcef13b | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 85 |         mFreezeDisplayTime(0), | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 86 |         mDebugRegion(0), | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 87 |         mDebugBackground(0), | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 88 |         mDebugInSwapBuffers(0), | 
 | 89 |         mLastSwapBufferTime(0), | 
 | 90 |         mDebugInTransaction(0), | 
 | 91 |         mLastTransactionTime(0), | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 92 |         mBootFinished(false), | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 93 |         mConsoleSignals(0), | 
 | 94 |         mSecureFrameBuffer(0) | 
 | 95 | { | 
 | 96 |     init(); | 
 | 97 | } | 
 | 98 |  | 
 | 99 | void SurfaceFlinger::init() | 
 | 100 | { | 
 | 101 |     LOGI("SurfaceFlinger is starting"); | 
 | 102 |  | 
 | 103 |     // debugging stuff... | 
 | 104 |     char value[PROPERTY_VALUE_MAX]; | 
 | 105 |     property_get("debug.sf.showupdates", value, "0"); | 
 | 106 |     mDebugRegion = atoi(value); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 107 |     property_get("debug.sf.showbackground", value, "0"); | 
 | 108 |     mDebugBackground = atoi(value); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 109 |  | 
| Mathias Agopian | 78fd501 | 2010-04-20 14:51:04 -0700 | [diff] [blame] | 110 |     LOGI_IF(mDebugRegion,       "showupdates enabled"); | 
 | 111 |     LOGI_IF(mDebugBackground,   "showbackground enabled"); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 112 | } | 
 | 113 |  | 
 | 114 | SurfaceFlinger::~SurfaceFlinger() | 
 | 115 | { | 
 | 116 |     glDeleteTextures(1, &mWormholeTexName); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 117 | } | 
 | 118 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 119 | overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const | 
 | 120 | { | 
 | 121 |     return graphicPlane(0).displayHardware().getOverlayEngine(); | 
 | 122 | } | 
 | 123 |  | 
| Mathias Agopian | 7303c6b | 2009-07-02 18:11:53 -0700 | [diff] [blame] | 124 | sp<IMemoryHeap> SurfaceFlinger::getCblk() const | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 125 | { | 
| Mathias Agopian | 7303c6b | 2009-07-02 18:11:53 -0700 | [diff] [blame] | 126 |     return mServerHeap; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 127 | } | 
 | 128 |  | 
| Mathias Agopian | 7e27f05 | 2010-05-28 14:22:23 -0700 | [diff] [blame] | 129 | sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 130 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 131 |     sp<ISurfaceComposerClient> bclient; | 
 | 132 |     sp<Client> client(new Client(this)); | 
 | 133 |     status_t err = client->initCheck(); | 
 | 134 |     if (err == NO_ERROR) { | 
 | 135 |         bclient = client; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 136 |     } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 137 |     return bclient; | 
 | 138 | } | 
 | 139 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 140 | sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection() | 
 | 141 | { | 
 | 142 |     sp<ISurfaceComposerClient> bclient; | 
 | 143 |     sp<UserClient> client(new UserClient(this)); | 
 | 144 |     status_t err = client->initCheck(); | 
 | 145 |     if (err == NO_ERROR) { | 
 | 146 |         bclient = client; | 
 | 147 |     } | 
 | 148 |     return bclient; | 
 | 149 | } | 
 | 150 |  | 
 | 151 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 152 | const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const | 
 | 153 | { | 
 | 154 |     LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy); | 
 | 155 |     const GraphicPlane& plane(mGraphicPlanes[dpy]); | 
 | 156 |     return plane; | 
 | 157 | } | 
 | 158 |  | 
 | 159 | GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) | 
 | 160 | { | 
 | 161 |     return const_cast<GraphicPlane&>( | 
 | 162 |         const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy)); | 
 | 163 | } | 
 | 164 |  | 
 | 165 | void SurfaceFlinger::bootFinished() | 
 | 166 | { | 
 | 167 |     const nsecs_t now = systemTime(); | 
 | 168 |     const nsecs_t duration = now - mBootTime; | 
| Mathias Agopian | a1ecca9 | 2009-05-21 19:21:59 -0700 | [diff] [blame] | 169 |     LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );   | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 170 |     mBootFinished = true; | 
| Mathias Agopian | a1ecca9 | 2009-05-21 19:21:59 -0700 | [diff] [blame] | 171 |     property_set("ctl.stop", "bootanim"); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 172 | } | 
 | 173 |  | 
 | 174 | void SurfaceFlinger::onFirstRef() | 
 | 175 | { | 
 | 176 |     run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); | 
 | 177 |  | 
 | 178 |     // Wait for the main thread to be done with its initialization | 
 | 179 |     mReadyToRunBarrier.wait(); | 
 | 180 | } | 
 | 181 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 182 | static inline uint16_t pack565(int r, int g, int b) { | 
 | 183 |     return (r<<11)|(g<<5)|b; | 
 | 184 | } | 
 | 185 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 186 | status_t SurfaceFlinger::readyToRun() | 
 | 187 | { | 
 | 188 |     LOGI(   "SurfaceFlinger's main thread ready to run. " | 
 | 189 |             "Initializing graphics H/W..."); | 
 | 190 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 191 |     // we only support one display currently | 
 | 192 |     int dpy = 0; | 
 | 193 |  | 
 | 194 |     { | 
 | 195 |         // initialize the main display | 
 | 196 |         GraphicPlane& plane(graphicPlane(dpy)); | 
 | 197 |         DisplayHardware* const hw = new DisplayHardware(this, dpy); | 
 | 198 |         plane.setDisplayHardware(hw); | 
 | 199 |     } | 
 | 200 |  | 
| Mathias Agopian | 7303c6b | 2009-07-02 18:11:53 -0700 | [diff] [blame] | 201 |     // create the shared control-block | 
 | 202 |     mServerHeap = new MemoryHeapBase(4096, | 
 | 203 |             MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap"); | 
 | 204 |     LOGE_IF(mServerHeap==0, "can't create shared memory dealer"); | 
 | 205 |      | 
 | 206 |     mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase()); | 
 | 207 |     LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); | 
 | 208 |      | 
 | 209 |     new(mServerCblk) surface_flinger_cblk_t; | 
 | 210 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 211 |     // initialize primary screen | 
 | 212 |     // (other display should be initialized in the same manner, but | 
 | 213 |     // asynchronously, as they could come and go. None of this is supported | 
 | 214 |     // yet). | 
 | 215 |     const GraphicPlane& plane(graphicPlane(dpy)); | 
 | 216 |     const DisplayHardware& hw = plane.displayHardware(); | 
 | 217 |     const uint32_t w = hw.getWidth(); | 
 | 218 |     const uint32_t h = hw.getHeight(); | 
 | 219 |     const uint32_t f = hw.getFormat(); | 
 | 220 |     hw.makeCurrent(); | 
 | 221 |  | 
 | 222 |     // initialize the shared control block | 
 | 223 |     mServerCblk->connected |= 1<<dpy; | 
 | 224 |     display_cblk_t* dcblk = mServerCblk->displays + dpy; | 
 | 225 |     memset(dcblk, 0, sizeof(display_cblk_t)); | 
| Mathias Agopian | 2b92d89 | 2010-02-08 15:49:35 -0800 | [diff] [blame] | 226 |     dcblk->w            = plane.getWidth(); | 
 | 227 |     dcblk->h            = plane.getHeight(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 228 |     dcblk->format       = f; | 
 | 229 |     dcblk->orientation  = ISurfaceComposer::eOrientationDefault; | 
 | 230 |     dcblk->xdpi         = hw.getDpiX(); | 
 | 231 |     dcblk->ydpi         = hw.getDpiY(); | 
 | 232 |     dcblk->fps          = hw.getRefreshRate(); | 
 | 233 |     dcblk->density      = hw.getDensity(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 234 |  | 
 | 235 |     // Initialize OpenGL|ES | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 236 |     glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | 
 | 237 |     glPixelStorei(GL_PACK_ALIGNMENT, 4);  | 
 | 238 |     glEnableClientState(GL_VERTEX_ARRAY); | 
 | 239 |     glEnable(GL_SCISSOR_TEST); | 
 | 240 |     glShadeModel(GL_FLAT); | 
 | 241 |     glDisable(GL_DITHER); | 
 | 242 |     glDisable(GL_CULL_FACE); | 
 | 243 |  | 
 | 244 |     const uint16_t g0 = pack565(0x0F,0x1F,0x0F); | 
 | 245 |     const uint16_t g1 = pack565(0x17,0x2f,0x17); | 
 | 246 |     const uint16_t textureData[4] = { g0, g1, g1, g0 }; | 
 | 247 |     glGenTextures(1, &mWormholeTexName); | 
 | 248 |     glBindTexture(GL_TEXTURE_2D, mWormholeTexName); | 
 | 249 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 
 | 250 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
 | 251 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | 
 | 252 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | 
 | 253 |     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, | 
 | 254 |             GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData); | 
 | 255 |  | 
 | 256 |     glViewport(0, 0, w, h); | 
 | 257 |     glMatrixMode(GL_PROJECTION); | 
 | 258 |     glLoadIdentity(); | 
 | 259 |     glOrthof(0, w, h, 0, 0, 1); | 
 | 260 |  | 
 | 261 |    LayerDim::initDimmer(this, w, h); | 
 | 262 |  | 
 | 263 |     mReadyToRunBarrier.open(); | 
 | 264 |  | 
 | 265 |     /* | 
 | 266 |      *  We're now ready to accept clients... | 
 | 267 |      */ | 
 | 268 |  | 
| Mathias Agopian | a1ecca9 | 2009-05-21 19:21:59 -0700 | [diff] [blame] | 269 |     // start boot animation | 
 | 270 |     property_set("ctl.start", "bootanim"); | 
 | 271 |      | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 272 |     return NO_ERROR; | 
 | 273 | } | 
 | 274 |  | 
 | 275 | // ---------------------------------------------------------------------------- | 
 | 276 | #if 0 | 
 | 277 | #pragma mark - | 
 | 278 | #pragma mark Events Handler | 
 | 279 | #endif | 
 | 280 |  | 
 | 281 | void SurfaceFlinger::waitForEvent() | 
 | 282 | { | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 283 |     while (true) { | 
 | 284 |         nsecs_t timeout = -1; | 
| Mathias Agopian | 0408772 | 2009-12-01 17:23:28 -0800 | [diff] [blame] | 285 |         const nsecs_t freezeDisplayTimeout = ms2ns(5000); | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 286 |         if (UNLIKELY(isFrozen())) { | 
 | 287 |             // wait 5 seconds | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 288 |             const nsecs_t now = systemTime(); | 
 | 289 |             if (mFreezeDisplayTime == 0) { | 
 | 290 |                 mFreezeDisplayTime = now; | 
 | 291 |             } | 
 | 292 |             nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); | 
 | 293 |             timeout = waitTime>0 ? waitTime : 0; | 
| The Android Open Source Project | bcef13b | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 294 |         } | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 295 |  | 
| Mathias Agopian | bb64124 | 2010-05-18 17:06:55 -0700 | [diff] [blame] | 296 |         sp<MessageBase> msg = mEventQueue.waitMessage(timeout); | 
| Mathias Agopian | 0408772 | 2009-12-01 17:23:28 -0800 | [diff] [blame] | 297 |  | 
 | 298 |         // see if we timed out | 
 | 299 |         if (isFrozen()) { | 
 | 300 |             const nsecs_t now = systemTime(); | 
 | 301 |             nsecs_t frozenTime = (now - mFreezeDisplayTime); | 
 | 302 |             if (frozenTime >= freezeDisplayTimeout) { | 
 | 303 |                 // we timed out and are still frozen | 
 | 304 |                 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", | 
 | 305 |                         mFreezeDisplay, mFreezeCount); | 
 | 306 |                 mFreezeDisplayTime = 0; | 
 | 307 |                 mFreezeCount = 0; | 
 | 308 |                 mFreezeDisplay = false; | 
 | 309 |             } | 
 | 310 |         } | 
 | 311 |  | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 312 |         if (msg != 0) { | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 313 |             switch (msg->what) { | 
 | 314 |                 case MessageQueue::INVALIDATE: | 
 | 315 |                     // invalidate message, just return to the main loop | 
 | 316 |                     return; | 
 | 317 |             } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 318 |         } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 319 |     } | 
 | 320 | } | 
 | 321 |  | 
 | 322 | void SurfaceFlinger::signalEvent() { | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 323 |     mEventQueue.invalidate(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 324 | } | 
 | 325 |  | 
 | 326 | void SurfaceFlinger::signal() const { | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 327 |     // this is the IPC call | 
 | 328 |     const_cast<SurfaceFlinger*>(this)->signalEvent(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 329 | } | 
 | 330 |  | 
| Mathias Agopian | bb64124 | 2010-05-18 17:06:55 -0700 | [diff] [blame] | 331 | status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, | 
 | 332 |         nsecs_t reltime, uint32_t flags) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 333 | { | 
| Mathias Agopian | bb64124 | 2010-05-18 17:06:55 -0700 | [diff] [blame] | 334 |     return mEventQueue.postMessage(msg, reltime, flags); | 
 | 335 | } | 
 | 336 |  | 
 | 337 | status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, | 
 | 338 |         nsecs_t reltime, uint32_t flags) | 
 | 339 | { | 
 | 340 |     status_t res = mEventQueue.postMessage(msg, reltime, flags); | 
 | 341 |     if (res == NO_ERROR) { | 
 | 342 |         msg->wait(); | 
 | 343 |     } | 
 | 344 |     return res; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 345 | } | 
 | 346 |  | 
 | 347 | // ---------------------------------------------------------------------------- | 
 | 348 | #if 0 | 
 | 349 | #pragma mark - | 
 | 350 | #pragma mark Main loop | 
 | 351 | #endif | 
 | 352 |  | 
 | 353 | bool SurfaceFlinger::threadLoop() | 
 | 354 | { | 
 | 355 |     waitForEvent(); | 
 | 356 |  | 
 | 357 |     // check for transactions | 
 | 358 |     if (UNLIKELY(mConsoleSignals)) { | 
 | 359 |         handleConsoleEvents(); | 
 | 360 |     } | 
 | 361 |  | 
 | 362 |     if (LIKELY(mTransactionCount == 0)) { | 
 | 363 |         // if we're in a global transaction, don't do anything. | 
 | 364 |         const uint32_t mask = eTransactionNeeded | eTraversalNeeded; | 
 | 365 |         uint32_t transactionFlags = getTransactionFlags(mask); | 
 | 366 |         if (LIKELY(transactionFlags)) { | 
 | 367 |             handleTransaction(transactionFlags); | 
 | 368 |         } | 
 | 369 |     } | 
 | 370 |  | 
 | 371 |     // post surfaces (if needed) | 
 | 372 |     handlePageFlip(); | 
 | 373 |  | 
 | 374 |     const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
| Mathias Agopian | 8a77baa | 2009-09-27 22:47:27 -0700 | [diff] [blame] | 375 |     if (LIKELY(hw.canDraw() && !isFrozen())) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 376 |         // repaint the framebuffer (if needed) | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 377 |  | 
 | 378 |         const int index = hw.getCurrentBufferIndex(); | 
 | 379 |         GraphicLog& logger(GraphicLog::getInstance()); | 
 | 380 |  | 
 | 381 |         logger.log(GraphicLog::SF_REPAINT, index); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 382 |         handleRepaint(); | 
 | 383 |  | 
| Mathias Agopian | 74faca2 | 2009-09-17 16:18:16 -0700 | [diff] [blame] | 384 |         // inform the h/w that we're done compositing | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 385 |         logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index); | 
| Mathias Agopian | 74faca2 | 2009-09-17 16:18:16 -0700 | [diff] [blame] | 386 |         hw.compositionComplete(); | 
 | 387 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 388 |         // release the clients before we flip ('cause flip might block) | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 389 |         logger.log(GraphicLog::SF_UNLOCK_CLIENTS, index); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 390 |         unlockClients(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 391 |  | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 392 |         logger.log(GraphicLog::SF_SWAP_BUFFERS, index); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 393 |         postFramebuffer(); | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 394 |  | 
 | 395 |         logger.log(GraphicLog::SF_REPAINT_DONE, index); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 396 |     } else { | 
 | 397 |         // pretend we did the post | 
 | 398 |         unlockClients(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 399 |         usleep(16667); // 60 fps period | 
 | 400 |     } | 
 | 401 |     return true; | 
 | 402 | } | 
 | 403 |  | 
 | 404 | void SurfaceFlinger::postFramebuffer() | 
 | 405 | { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 406 |     if (!mInvalidRegion.isEmpty()) { | 
 | 407 |         const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 408 |         const nsecs_t now = systemTime(); | 
 | 409 |         mDebugInSwapBuffers = now; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 410 |         hw.flip(mInvalidRegion); | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 411 |         mLastSwapBufferTime = systemTime() - now; | 
 | 412 |         mDebugInSwapBuffers = 0; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 413 |         mInvalidRegion.clear(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 414 |     } | 
 | 415 | } | 
 | 416 |  | 
 | 417 | void SurfaceFlinger::handleConsoleEvents() | 
 | 418 | { | 
 | 419 |     // something to do with the console | 
 | 420 |     const DisplayHardware& hw = graphicPlane(0).displayHardware(); | 
 | 421 |  | 
 | 422 |     int what = android_atomic_and(0, &mConsoleSignals); | 
 | 423 |     if (what & eConsoleAcquired) { | 
 | 424 |         hw.acquireScreen(); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 425 |         // this is a temporary work-around, eventually this should be called | 
 | 426 |         // by the power-manager | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 427 |         SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 428 |     } | 
 | 429 |  | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 430 |     if (mDeferReleaseConsole && hw.isScreenAcquired()) { | 
| Mathias Agopian | 62b7444 | 2009-04-14 23:02:51 -0700 | [diff] [blame] | 431 |         // We got the release signal before the acquire signal | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 432 |         mDeferReleaseConsole = false; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 433 |         hw.releaseScreen(); | 
 | 434 |     } | 
 | 435 |  | 
 | 436 |     if (what & eConsoleReleased) { | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 437 |         if (hw.isScreenAcquired()) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 438 |             hw.releaseScreen(); | 
 | 439 |         } else { | 
 | 440 |             mDeferReleaseConsole = true; | 
 | 441 |         } | 
 | 442 |     } | 
 | 443 |  | 
 | 444 |     mDirtyRegion.set(hw.bounds()); | 
 | 445 | } | 
 | 446 |  | 
 | 447 | void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) | 
 | 448 | { | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 449 |     Vector< sp<LayerBase> > ditchedLayers; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 450 |  | 
| Mathias Agopian | 4da7519 | 2010-08-10 17:19:56 -0700 | [diff] [blame] | 451 |     /* | 
 | 452 |      * Perform and commit the transaction | 
 | 453 |      */ | 
 | 454 |  | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 455 |     { // scope for the lock | 
 | 456 |         Mutex::Autolock _l(mStateLock); | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 457 |         const nsecs_t now = systemTime(); | 
 | 458 |         mDebugInTransaction = now; | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 459 |         handleTransactionLocked(transactionFlags, ditchedLayers); | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 460 |         mLastTransactionTime = systemTime() - now; | 
 | 461 |         mDebugInTransaction = 0; | 
| Mathias Agopian | 4da7519 | 2010-08-10 17:19:56 -0700 | [diff] [blame] | 462 |         // here the transaction has been committed | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 463 |     } | 
 | 464 |  | 
| Mathias Agopian | 4da7519 | 2010-08-10 17:19:56 -0700 | [diff] [blame] | 465 |     /* | 
 | 466 |      * Clean-up all layers that went away | 
 | 467 |      * (do this without the lock held) | 
 | 468 |      */ | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 469 |     const size_t count = ditchedLayers.size(); | 
 | 470 |     for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | 0852e67 | 2009-09-04 19:50:23 -0700 | [diff] [blame] | 471 |         if (ditchedLayers[i] != 0) { | 
 | 472 |             //LOGD("ditching layer %p", ditchedLayers[i].get()); | 
 | 473 |             ditchedLayers[i]->ditch(); | 
 | 474 |         } | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 475 |     } | 
 | 476 | } | 
 | 477 |  | 
 | 478 | void SurfaceFlinger::handleTransactionLocked( | 
 | 479 |         uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers) | 
 | 480 | { | 
 | 481 |     const LayerVector& currentLayers(mCurrentState.layersSortedByZ); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 482 |     const size_t count = currentLayers.size(); | 
 | 483 |  | 
 | 484 |     /* | 
 | 485 |      * Traversal of the children | 
 | 486 |      * (perform the transaction for each of them if needed) | 
 | 487 |      */ | 
 | 488 |  | 
 | 489 |     const bool layersNeedTransaction = transactionFlags & eTraversalNeeded; | 
 | 490 |     if (layersNeedTransaction) { | 
 | 491 |         for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 492 |             const sp<LayerBase>& layer = currentLayers[i]; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 493 |             uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); | 
 | 494 |             if (!trFlags) continue; | 
 | 495 |  | 
 | 496 |             const uint32_t flags = layer->doTransaction(0); | 
 | 497 |             if (flags & Layer::eVisibleRegion) | 
 | 498 |                 mVisibleRegionsDirty = true; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 499 |         } | 
 | 500 |     } | 
 | 501 |  | 
 | 502 |     /* | 
 | 503 |      * Perform our own transaction if needed | 
 | 504 |      */ | 
 | 505 |  | 
 | 506 |     if (transactionFlags & eTransactionNeeded) { | 
 | 507 |         if (mCurrentState.orientation != mDrawingState.orientation) { | 
 | 508 |             // the orientation has changed, recompute all visible regions | 
 | 509 |             // and invalidate everything. | 
 | 510 |  | 
 | 511 |             const int dpy = 0; | 
 | 512 |             const int orientation = mCurrentState.orientation; | 
| Mathias Agopian | c08731e | 2009-03-27 18:11:38 -0700 | [diff] [blame] | 513 |             const uint32_t type = mCurrentState.orientationType; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 514 |             GraphicPlane& plane(graphicPlane(dpy)); | 
 | 515 |             plane.setOrientation(orientation); | 
 | 516 |  | 
 | 517 |             // update the shared control block | 
 | 518 |             const DisplayHardware& hw(plane.displayHardware()); | 
 | 519 |             volatile display_cblk_t* dcblk = mServerCblk->displays + dpy; | 
 | 520 |             dcblk->orientation = orientation; | 
| Mathias Agopian | 2b92d89 | 2010-02-08 15:49:35 -0800 | [diff] [blame] | 521 |             dcblk->w = plane.getWidth(); | 
 | 522 |             dcblk->h = plane.getHeight(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 523 |  | 
 | 524 |             mVisibleRegionsDirty = true; | 
 | 525 |             mDirtyRegion.set(hw.bounds()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 526 |         } | 
 | 527 |  | 
 | 528 |         if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { | 
 | 529 |             // freezing or unfreezing the display -> trigger animation if needed | 
 | 530 |             mFreezeDisplay = mCurrentState.freezeDisplay; | 
| Mathias Agopian | 064e1e6 | 2010-03-01 17:51:17 -0800 | [diff] [blame] | 531 |             if (mFreezeDisplay) | 
 | 532 |                  mFreezeDisplayTime = 0; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 533 |         } | 
 | 534 |  | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 535 |         if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { | 
 | 536 |             // layers have been added | 
 | 537 |             mVisibleRegionsDirty = true; | 
 | 538 |         } | 
 | 539 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 540 |         // some layers might have been removed, so | 
 | 541 |         // we need to update the regions they're exposing. | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 542 |         if (mLayersRemoved) { | 
| Mathias Agopian | 48d819a | 2009-09-10 19:41:18 -0700 | [diff] [blame] | 543 |             mLayersRemoved = false; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 544 |             mVisibleRegionsDirty = true; | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 545 |             const LayerVector& previousLayers(mDrawingState.layersSortedByZ); | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 546 |             const size_t count = previousLayers.size(); | 
 | 547 |             for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 548 |                 const sp<LayerBase>& layer(previousLayers[i]); | 
 | 549 |                 if (currentLayers.indexOf( layer ) < 0) { | 
 | 550 |                     // this layer is not visible anymore | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 551 |                     ditchedLayers.add(layer); | 
| Mathias Agopian | 5d7126b | 2009-07-28 14:20:21 -0700 | [diff] [blame] | 552 |                     mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen); | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 553 |                 } | 
 | 554 |             } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 555 |         } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 556 |     } | 
 | 557 |  | 
 | 558 |     commitTransaction(); | 
 | 559 | } | 
 | 560 |  | 
 | 561 | sp<FreezeLock> SurfaceFlinger::getFreezeLock() const | 
 | 562 | { | 
 | 563 |     return new FreezeLock(const_cast<SurfaceFlinger *>(this)); | 
 | 564 | } | 
 | 565 |  | 
 | 566 | void SurfaceFlinger::computeVisibleRegions( | 
 | 567 |     LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion) | 
 | 568 | { | 
 | 569 |     const GraphicPlane& plane(graphicPlane(0)); | 
 | 570 |     const Transform& planeTransform(plane.transform()); | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 571 |     const DisplayHardware& hw(plane.displayHardware()); | 
 | 572 |     const Region screenRegion(hw.bounds()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 573 |  | 
 | 574 |     Region aboveOpaqueLayers; | 
 | 575 |     Region aboveCoveredLayers; | 
 | 576 |     Region dirty; | 
 | 577 |  | 
 | 578 |     bool secureFrameBuffer = false; | 
 | 579 |  | 
 | 580 |     size_t i = currentLayers.size(); | 
 | 581 |     while (i--) { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 582 |         const sp<LayerBase>& layer = currentLayers[i]; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 583 |         layer->validateVisibility(planeTransform); | 
 | 584 |  | 
 | 585 |         // start with the whole surface at its current location | 
| Mathias Agopian | 9701122 | 2009-07-28 10:57:27 -0700 | [diff] [blame] | 586 |         const Layer::State& s(layer->drawingState()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 587 |  | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 588 |         /* | 
 | 589 |          * opaqueRegion: area of a surface that is fully opaque. | 
 | 590 |          */ | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 591 |         Region opaqueRegion; | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 592 |  | 
 | 593 |         /* | 
 | 594 |          * visibleRegion: area of a surface that is visible on screen | 
 | 595 |          * and not fully transparent. This is essentially the layer's | 
 | 596 |          * footprint minus the opaque regions above it. | 
 | 597 |          * Areas covered by a translucent surface are considered visible. | 
 | 598 |          */ | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 599 |         Region visibleRegion; | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 600 |  | 
 | 601 |         /* | 
 | 602 |          * coveredRegion: area of a surface that is covered by all | 
 | 603 |          * visible regions above it (which includes the translucent areas). | 
 | 604 |          */ | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 605 |         Region coveredRegion; | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 606 |  | 
 | 607 |  | 
 | 608 |         // handle hidden surfaces by setting the visible region to empty | 
| Mathias Agopian | 9701122 | 2009-07-28 10:57:27 -0700 | [diff] [blame] | 609 |         if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 610 |             const bool translucent = layer->needsBlending(); | 
| Mathias Agopian | 9701122 | 2009-07-28 10:57:27 -0700 | [diff] [blame] | 611 |             const Rect bounds(layer->visibleBounds()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 612 |             visibleRegion.set(bounds); | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 613 |             visibleRegion.andSelf(screenRegion); | 
 | 614 |             if (!visibleRegion.isEmpty()) { | 
 | 615 |                 // Remove the transparent area from the visible region | 
 | 616 |                 if (translucent) { | 
 | 617 |                     visibleRegion.subtractSelf(layer->transparentRegionScreen); | 
 | 618 |                 } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 619 |  | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 620 |                 // compute the opaque region | 
 | 621 |                 const int32_t layerOrientation = layer->getOrientation(); | 
 | 622 |                 if (s.alpha==255 && !translucent && | 
 | 623 |                         ((layerOrientation & Transform::ROT_INVALID) == false)) { | 
 | 624 |                     // the opaque region is the layer's footprint | 
 | 625 |                     opaqueRegion = visibleRegion; | 
 | 626 |                 } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 627 |             } | 
 | 628 |         } | 
 | 629 |  | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 630 |         // Clip the covered region to the visible region | 
 | 631 |         coveredRegion = aboveCoveredLayers.intersect(visibleRegion); | 
 | 632 |  | 
 | 633 |         // Update aboveCoveredLayers for next (lower) layer | 
 | 634 |         aboveCoveredLayers.orSelf(visibleRegion); | 
 | 635 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 636 |         // subtract the opaque region covered by the layers above us | 
 | 637 |         visibleRegion.subtractSelf(aboveOpaqueLayers); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 638 |  | 
 | 639 |         // compute this layer's dirty region | 
 | 640 |         if (layer->contentDirty) { | 
 | 641 |             // we need to invalidate the whole region | 
 | 642 |             dirty = visibleRegion; | 
 | 643 |             // as well, as the old visible region | 
 | 644 |             dirty.orSelf(layer->visibleRegionScreen); | 
 | 645 |             layer->contentDirty = false; | 
 | 646 |         } else { | 
| Mathias Agopian | a8d44f7 | 2009-06-28 02:54:16 -0700 | [diff] [blame] | 647 |             /* compute the exposed region: | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 648 |              *   the exposed region consists of two components: | 
 | 649 |              *   1) what's VISIBLE now and was COVERED before | 
 | 650 |              *   2) what's EXPOSED now less what was EXPOSED before | 
 | 651 |              * | 
 | 652 |              * note that (1) is conservative, we start with the whole | 
 | 653 |              * visible region but only keep what used to be covered by | 
 | 654 |              * something -- which mean it may have been exposed. | 
 | 655 |              * | 
 | 656 |              * (2) handles areas that were not covered by anything but got | 
 | 657 |              * exposed because of a resize. | 
| Mathias Agopian | a8d44f7 | 2009-06-28 02:54:16 -0700 | [diff] [blame] | 658 |              */ | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 659 |             const Region newExposed = visibleRegion - coveredRegion; | 
 | 660 |             const Region oldVisibleRegion = layer->visibleRegionScreen; | 
 | 661 |             const Region oldCoveredRegion = layer->coveredRegionScreen; | 
 | 662 |             const Region oldExposed = oldVisibleRegion - oldCoveredRegion; | 
 | 663 |             dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 664 |         } | 
 | 665 |         dirty.subtractSelf(aboveOpaqueLayers); | 
 | 666 |  | 
 | 667 |         // accumulate to the screen dirty region | 
 | 668 |         dirtyRegion.orSelf(dirty); | 
 | 669 |  | 
| Mathias Agopian | ab02873 | 2010-03-16 16:41:46 -0700 | [diff] [blame] | 670 |         // Update aboveOpaqueLayers for next (lower) layer | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 671 |         aboveOpaqueLayers.orSelf(opaqueRegion); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 672 |          | 
 | 673 |         // Store the visible region is screen space | 
 | 674 |         layer->setVisibleRegion(visibleRegion); | 
 | 675 |         layer->setCoveredRegion(coveredRegion); | 
 | 676 |  | 
| Mathias Agopian | 9701122 | 2009-07-28 10:57:27 -0700 | [diff] [blame] | 677 |         // If a secure layer is partially visible, lock-down the screen! | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 678 |         if (layer->isSecure() && !visibleRegion.isEmpty()) { | 
 | 679 |             secureFrameBuffer = true; | 
 | 680 |         } | 
 | 681 |     } | 
 | 682 |  | 
| Mathias Agopian | 9701122 | 2009-07-28 10:57:27 -0700 | [diff] [blame] | 683 |     // invalidate the areas where a layer was removed | 
 | 684 |     dirtyRegion.orSelf(mDirtyRegionRemovedLayer); | 
 | 685 |     mDirtyRegionRemovedLayer.clear(); | 
 | 686 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 687 |     mSecureFrameBuffer = secureFrameBuffer; | 
 | 688 |     opaqueRegion = aboveOpaqueLayers; | 
 | 689 | } | 
 | 690 |  | 
 | 691 |  | 
 | 692 | void SurfaceFlinger::commitTransaction() | 
 | 693 | { | 
 | 694 |     mDrawingState = mCurrentState; | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 695 |     mResizeTransationPending = false; | 
 | 696 |     mTransactionCV.broadcast(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 697 | } | 
 | 698 |  | 
 | 699 | void SurfaceFlinger::handlePageFlip() | 
 | 700 | { | 
 | 701 |     bool visibleRegions = mVisibleRegionsDirty; | 
| Mathias Agopian | 000ca8f | 2010-08-17 20:19:23 -0700 | [diff] [blame] | 702 |     LayerVector& currentLayers = const_cast<LayerVector&>( | 
 | 703 |             mDrawingState.layersSortedByZ); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 704 |     visibleRegions |= lockPageFlip(currentLayers); | 
 | 705 |  | 
 | 706 |         const DisplayHardware& hw = graphicPlane(0).displayHardware(); | 
 | 707 |         const Region screenRegion(hw.bounds()); | 
 | 708 |         if (visibleRegions) { | 
 | 709 |             Region opaqueRegion; | 
 | 710 |             computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion); | 
| Mathias Agopian | 4da7519 | 2010-08-10 17:19:56 -0700 | [diff] [blame] | 711 |  | 
 | 712 |             /* | 
 | 713 |              *  rebuild the visible layer list | 
 | 714 |              */ | 
 | 715 |             mVisibleLayersSortedByZ.clear(); | 
 | 716 |             const LayerVector& currentLayers(mDrawingState.layersSortedByZ); | 
 | 717 |             size_t count = currentLayers.size(); | 
 | 718 |             mVisibleLayersSortedByZ.setCapacity(count); | 
 | 719 |             for (size_t i=0 ; i<count ; i++) { | 
 | 720 |                 if (!currentLayers[i]->visibleRegionScreen.isEmpty()) | 
 | 721 |                     mVisibleLayersSortedByZ.add(currentLayers[i]); | 
 | 722 |             } | 
 | 723 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 724 |             mWormholeRegion = screenRegion.subtract(opaqueRegion); | 
 | 725 |             mVisibleRegionsDirty = false; | 
 | 726 |         } | 
 | 727 |  | 
 | 728 |     unlockPageFlip(currentLayers); | 
 | 729 |     mDirtyRegion.andSelf(screenRegion); | 
 | 730 | } | 
 | 731 |  | 
 | 732 | bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) | 
 | 733 | { | 
 | 734 |     bool recomputeVisibleRegions = false; | 
 | 735 |     size_t count = currentLayers.size(); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 736 |     sp<LayerBase> const* layers = currentLayers.array(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 737 |     for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 738 |         const sp<LayerBase>& layer(layers[i]); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 739 |         layer->lockPageFlip(recomputeVisibleRegions); | 
 | 740 |     } | 
 | 741 |     return recomputeVisibleRegions; | 
 | 742 | } | 
 | 743 |  | 
 | 744 | void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) | 
 | 745 | { | 
 | 746 |     const GraphicPlane& plane(graphicPlane(0)); | 
 | 747 |     const Transform& planeTransform(plane.transform()); | 
 | 748 |     size_t count = currentLayers.size(); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 749 |     sp<LayerBase> const* layers = currentLayers.array(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 750 |     for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 751 |         const sp<LayerBase>& layer(layers[i]); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 752 |         layer->unlockPageFlip(planeTransform, mDirtyRegion); | 
 | 753 |     } | 
 | 754 | } | 
 | 755 |  | 
| Mathias Agopian | b8a5560 | 2009-06-26 19:06:36 -0700 | [diff] [blame] | 756 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 757 | void SurfaceFlinger::handleRepaint() | 
 | 758 | { | 
| Mathias Agopian | b8a5560 | 2009-06-26 19:06:36 -0700 | [diff] [blame] | 759 |     // compute the invalid region | 
 | 760 |     mInvalidRegion.orSelf(mDirtyRegion); | 
 | 761 |     if (mInvalidRegion.isEmpty()) { | 
 | 762 |         // nothing to do | 
 | 763 |         return; | 
 | 764 |     } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 765 |  | 
 | 766 |     if (UNLIKELY(mDebugRegion)) { | 
 | 767 |         debugFlashRegions(); | 
 | 768 |     } | 
 | 769 |  | 
| Mathias Agopian | b8a5560 | 2009-06-26 19:06:36 -0700 | [diff] [blame] | 770 |     // set the frame buffer | 
 | 771 |     const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 772 |     glMatrixMode(GL_MODELVIEW); | 
 | 773 |     glLoadIdentity(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 774 |  | 
 | 775 |     uint32_t flags = hw.getFlags(); | 
| Mathias Agopian | df3ca30 | 2009-05-04 19:29:25 -0700 | [diff] [blame] | 776 |     if ((flags & DisplayHardware::SWAP_RECTANGLE) ||  | 
 | 777 |         (flags & DisplayHardware::BUFFER_PRESERVED))  | 
 | 778 |     { | 
| Mathias Agopian | 29d06ac | 2009-06-29 18:49:56 -0700 | [diff] [blame] | 779 |         // we can redraw only what's dirty, but since SWAP_RECTANGLE only | 
 | 780 |         // takes a rectangle, we must make sure to update that whole | 
 | 781 |         // rectangle in that case | 
 | 782 |         if (flags & DisplayHardware::SWAP_RECTANGLE) { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 783 |             // TODO: we really should be able to pass a region to | 
| Mathias Agopian | 29d06ac | 2009-06-29 18:49:56 -0700 | [diff] [blame] | 784 |             // SWAP_RECTANGLE so that we don't have to redraw all this. | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 785 |             mDirtyRegion.set(mInvalidRegion.bounds()); | 
 | 786 |         } else { | 
| Mathias Agopian | 29d06ac | 2009-06-29 18:49:56 -0700 | [diff] [blame] | 787 |             // in the BUFFER_PRESERVED case, obviously, we can update only | 
 | 788 |             // what's needed and nothing more. | 
 | 789 |             // NOTE: this is NOT a common case, as preserving the backbuffer | 
 | 790 |             // is costly and usually involves copying the whole update back. | 
 | 791 |         } | 
 | 792 |     } else { | 
| Mathias Agopian | 95a666b | 2009-09-24 14:57:26 -0700 | [diff] [blame] | 793 |         if (flags & DisplayHardware::PARTIAL_UPDATES) { | 
| Mathias Agopian | 29d06ac | 2009-06-29 18:49:56 -0700 | [diff] [blame] | 794 |             // We need to redraw the rectangle that will be updated | 
 | 795 |             // (pushed to the framebuffer). | 
| Mathias Agopian | 95a666b | 2009-09-24 14:57:26 -0700 | [diff] [blame] | 796 |             // This is needed because PARTIAL_UPDATES only takes one | 
| Mathias Agopian | 29d06ac | 2009-06-29 18:49:56 -0700 | [diff] [blame] | 797 |             // rectangle instead of a region (see DisplayHardware::flip()) | 
 | 798 |             mDirtyRegion.set(mInvalidRegion.bounds()); | 
 | 799 |         } else { | 
 | 800 |             // we need to redraw everything (the whole screen) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 801 |             mDirtyRegion.set(hw.bounds()); | 
 | 802 |             mInvalidRegion = mDirtyRegion; | 
 | 803 |         } | 
 | 804 |     } | 
 | 805 |  | 
 | 806 |     // compose all surfaces | 
 | 807 |     composeSurfaces(mDirtyRegion); | 
 | 808 |  | 
 | 809 |     // clear the dirty regions | 
 | 810 |     mDirtyRegion.clear(); | 
 | 811 | } | 
 | 812 |  | 
 | 813 | void SurfaceFlinger::composeSurfaces(const Region& dirty) | 
 | 814 | { | 
 | 815 |     if (UNLIKELY(!mWormholeRegion.isEmpty())) { | 
 | 816 |         // should never happen unless the window manager has a bug | 
 | 817 |         // draw something... | 
 | 818 |         drawWormhole(); | 
 | 819 |     } | 
| Mathias Agopian | 4da7519 | 2010-08-10 17:19:56 -0700 | [diff] [blame] | 820 |     const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); | 
| Mathias Agopian | 000ca8f | 2010-08-17 20:19:23 -0700 | [diff] [blame] | 821 |     const size_t count = layers.size(); | 
 | 822 |     for (size_t i=0 ; i<count ; ++i) { | 
| Mathias Agopian | 4572177 | 2010-08-12 15:03:26 -0700 | [diff] [blame] | 823 |         const sp<LayerBase>& layer(layers[i]); | 
 | 824 |         const Region clip(dirty.intersect(layer->visibleRegionScreen)); | 
 | 825 |         if (!clip.isEmpty()) { | 
 | 826 |             layer->draw(clip); | 
 | 827 |         } | 
 | 828 |     } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 829 | } | 
 | 830 |  | 
 | 831 | void SurfaceFlinger::unlockClients() | 
 | 832 | { | 
 | 833 |     const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); | 
 | 834 |     const size_t count = drawingLayers.size(); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 835 |     sp<LayerBase> const* const layers = drawingLayers.array(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 836 |     for (size_t i=0 ; i<count ; ++i) { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 837 |         const sp<LayerBase>& layer = layers[i]; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 838 |         layer->finishPageFlip(); | 
 | 839 |     } | 
 | 840 | } | 
 | 841 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 842 | void SurfaceFlinger::debugFlashRegions() | 
 | 843 | { | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 844 |     const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 845 |     const uint32_t flags = hw.getFlags(); | 
| Mathias Agopian | df3ca30 | 2009-05-04 19:29:25 -0700 | [diff] [blame] | 846 |  | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 847 |     if (!((flags & DisplayHardware::SWAP_RECTANGLE) || | 
 | 848 |             (flags & DisplayHardware::BUFFER_PRESERVED))) { | 
 | 849 |         const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ? | 
 | 850 |                 mDirtyRegion.bounds() : hw.bounds()); | 
 | 851 |         composeSurfaces(repaint); | 
 | 852 |     } | 
 | 853 |  | 
 | 854 |     TextureManager::deactivateTextures(); | 
 | 855 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 856 |     glDisable(GL_BLEND); | 
 | 857 |     glDisable(GL_DITHER); | 
 | 858 |     glDisable(GL_SCISSOR_TEST); | 
 | 859 |  | 
| Mathias Agopian | 0926f50 | 2009-05-04 14:17:04 -0700 | [diff] [blame] | 860 |     static int toggle = 0; | 
 | 861 |     toggle = 1 - toggle; | 
 | 862 |     if (toggle) { | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 863 |         glColor4f(1, 0, 1, 1); | 
| Mathias Agopian | 0926f50 | 2009-05-04 14:17:04 -0700 | [diff] [blame] | 864 |     } else { | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 865 |         glColor4f(1, 1, 0, 1); | 
| Mathias Agopian | 0926f50 | 2009-05-04 14:17:04 -0700 | [diff] [blame] | 866 |     } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 867 |  | 
| Mathias Agopian | 20f6878 | 2009-05-11 00:03:41 -0700 | [diff] [blame] | 868 |     Region::const_iterator it = mDirtyRegion.begin(); | 
 | 869 |     Region::const_iterator const end = mDirtyRegion.end(); | 
 | 870 |     while (it != end) { | 
 | 871 |         const Rect& r = *it++; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 872 |         GLfloat vertices[][2] = { | 
 | 873 |                 { r.left,  r.top }, | 
 | 874 |                 { r.left,  r.bottom }, | 
 | 875 |                 { r.right, r.bottom }, | 
 | 876 |                 { r.right, r.top } | 
 | 877 |         }; | 
 | 878 |         glVertexPointer(2, GL_FLOAT, 0, vertices); | 
 | 879 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 880 |     } | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 881 |  | 
| Mathias Agopian | b8a5560 | 2009-06-26 19:06:36 -0700 | [diff] [blame] | 882 |     if (mInvalidRegion.isEmpty()) { | 
 | 883 |         mDirtyRegion.dump("mDirtyRegion"); | 
 | 884 |         mInvalidRegion.dump("mInvalidRegion"); | 
 | 885 |     } | 
 | 886 |     hw.flip(mInvalidRegion); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 887 |  | 
 | 888 |     if (mDebugRegion > 1) | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 889 |         usleep(mDebugRegion * 1000); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 890 |  | 
 | 891 |     glEnable(GL_SCISSOR_TEST); | 
 | 892 |     //mDirtyRegion.dump("mDirtyRegion"); | 
 | 893 | } | 
 | 894 |  | 
 | 895 | void SurfaceFlinger::drawWormhole() const | 
 | 896 | { | 
 | 897 |     const Region region(mWormholeRegion.intersect(mDirtyRegion)); | 
 | 898 |     if (region.isEmpty()) | 
 | 899 |         return; | 
 | 900 |  | 
 | 901 |     const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 902 |     const int32_t width = hw.getWidth(); | 
 | 903 |     const int32_t height = hw.getHeight(); | 
 | 904 |  | 
 | 905 |     glDisable(GL_BLEND); | 
 | 906 |     glDisable(GL_DITHER); | 
 | 907 |  | 
 | 908 |     if (LIKELY(!mDebugBackground)) { | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 909 |         glClearColor(0,0,0,0); | 
| Mathias Agopian | 20f6878 | 2009-05-11 00:03:41 -0700 | [diff] [blame] | 910 |         Region::const_iterator it = region.begin(); | 
 | 911 |         Region::const_iterator const end = region.end(); | 
 | 912 |         while (it != end) { | 
 | 913 |             const Rect& r = *it++; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 914 |             const GLint sy = height - (r.top + r.height()); | 
 | 915 |             glScissor(r.left, sy, r.width(), r.height()); | 
 | 916 |             glClear(GL_COLOR_BUFFER_BIT); | 
 | 917 |         } | 
 | 918 |     } else { | 
 | 919 |         const GLshort vertices[][2] = { { 0, 0 }, { width, 0 }, | 
 | 920 |                 { width, height }, { 0, height }  }; | 
 | 921 |         const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 },  { 1, 1 }, { 0, 1 } }; | 
 | 922 |         glVertexPointer(2, GL_SHORT, 0, vertices); | 
 | 923 |         glTexCoordPointer(2, GL_SHORT, 0, tcoords); | 
 | 924 |         glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 
| Michael I. Gold | 7f198b6 | 2010-09-15 15:46:24 -0700 | [diff] [blame] | 925 | #if defined(GL_OES_EGL_image_external) | 
| Mathias Agopian | 1f7bec6 | 2010-06-25 18:02:21 -0700 | [diff] [blame] | 926 |         if (GLExtensions::getInstance().haveTextureExternal()) { | 
 | 927 |             glDisable(GL_TEXTURE_EXTERNAL_OES); | 
 | 928 |         } | 
| Mathias Agopian | 0a91775 | 2010-06-14 21:20:00 -0700 | [diff] [blame] | 929 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 930 |         glEnable(GL_TEXTURE_2D); | 
 | 931 |         glBindTexture(GL_TEXTURE_2D, mWormholeTexName); | 
 | 932 |         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | 
 | 933 |         glMatrixMode(GL_TEXTURE); | 
 | 934 |         glLoadIdentity(); | 
 | 935 |         glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1); | 
| Mathias Agopian | 20f6878 | 2009-05-11 00:03:41 -0700 | [diff] [blame] | 936 |         Region::const_iterator it = region.begin(); | 
 | 937 |         Region::const_iterator const end = region.end(); | 
 | 938 |         while (it != end) { | 
 | 939 |             const Rect& r = *it++; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 940 |             const GLint sy = height - (r.top + r.height()); | 
 | 941 |             glScissor(r.left, sy, r.width(), r.height()); | 
 | 942 |             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 943 |         } | 
 | 944 |         glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 
 | 945 |     } | 
 | 946 | } | 
 | 947 |  | 
 | 948 | void SurfaceFlinger::debugShowFPS() const | 
 | 949 | { | 
 | 950 |     static int mFrameCount; | 
 | 951 |     static int mLastFrameCount = 0; | 
 | 952 |     static nsecs_t mLastFpsTime = 0; | 
 | 953 |     static float mFps = 0; | 
 | 954 |     mFrameCount++; | 
 | 955 |     nsecs_t now = systemTime(); | 
 | 956 |     nsecs_t diff = now - mLastFpsTime; | 
 | 957 |     if (diff > ms2ns(250)) { | 
 | 958 |         mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; | 
 | 959 |         mLastFpsTime = now; | 
 | 960 |         mLastFrameCount = mFrameCount; | 
 | 961 |     } | 
 | 962 |     // XXX: mFPS has the value we want | 
 | 963 |  } | 
 | 964 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 965 | status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 966 | { | 
 | 967 |     Mutex::Autolock _l(mStateLock); | 
 | 968 |     addLayer_l(layer); | 
 | 969 |     setTransactionFlags(eTransactionNeeded|eTraversalNeeded); | 
 | 970 |     return NO_ERROR; | 
 | 971 | } | 
 | 972 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 973 | status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) | 
 | 974 | { | 
| Mathias Agopian | f6679fc | 2010-08-10 18:09:09 -0700 | [diff] [blame] | 975 |     ssize_t i = mCurrentState.layersSortedByZ.add(layer); | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 976 |     return (i < 0) ? status_t(i) : status_t(NO_ERROR); | 
 | 977 | } | 
 | 978 |  | 
 | 979 | ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client, | 
 | 980 |         const sp<LayerBaseClient>& lbc) | 
 | 981 | { | 
 | 982 |     Mutex::Autolock _l(mStateLock); | 
 | 983 |  | 
 | 984 |     // attach this layer to the client | 
 | 985 |     ssize_t name = client->attachLayer(lbc); | 
 | 986 |  | 
 | 987 |     // add this layer to the current state list | 
 | 988 |     addLayer_l(lbc); | 
 | 989 |  | 
 | 990 |     return name; | 
 | 991 | } | 
 | 992 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 993 | status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 994 | { | 
 | 995 |     Mutex::Autolock _l(mStateLock); | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 996 |     status_t err = purgatorizeLayer_l(layer); | 
 | 997 |     if (err == NO_ERROR) | 
 | 998 |         setTransactionFlags(eTransactionNeeded); | 
 | 999 |     return err; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1000 | } | 
 | 1001 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1002 | status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1003 | { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1004 |     sp<LayerBaseClient> lbc(layerBase->getLayerBaseClient()); | 
 | 1005 |     if (lbc != 0) { | 
 | 1006 |         mLayerMap.removeItem( lbc->getSurface()->asBinder() ); | 
 | 1007 |     } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1008 |     ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); | 
 | 1009 |     if (index >= 0) { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1010 |         mLayersRemoved = true; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1011 |         return NO_ERROR; | 
 | 1012 |     } | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 1013 |     return status_t(index); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1014 | } | 
 | 1015 |  | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1016 | status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase) | 
 | 1017 | { | 
| Mathias Agopian | 8c0a3d7 | 2009-09-23 16:44:00 -0700 | [diff] [blame] | 1018 |     // remove the layer from the main list (through a transaction). | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1019 |     ssize_t err = removeLayer_l(layerBase); | 
| Mathias Agopian | 8c0a3d7 | 2009-09-23 16:44:00 -0700 | [diff] [blame] | 1020 |  | 
| Mathias Agopian | 0b3ad46 | 2009-10-02 18:12:30 -0700 | [diff] [blame] | 1021 |     layerBase->onRemoved(); | 
 | 1022 |  | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 1023 |     // it's possible that we don't find a layer, because it might | 
 | 1024 |     // have been destroyed already -- this is not technically an error | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1025 |     // from the user because there is a race between Client::destroySurface(), | 
 | 1026 |     // ~Client() and ~ISurface(). | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1027 |     return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err; | 
 | 1028 | } | 
 | 1029 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1030 | status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1031 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1032 |     layer->forceVisibilityTransaction(); | 
 | 1033 |     setTransactionFlags(eTraversalNeeded); | 
 | 1034 |     return NO_ERROR; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1035 | } | 
 | 1036 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1037 | uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) | 
 | 1038 | { | 
 | 1039 |     return android_atomic_and(~flags, &mTransactionFlags) & flags; | 
 | 1040 | } | 
 | 1041 |  | 
| Mathias Agopian | bb64124 | 2010-05-18 17:06:55 -0700 | [diff] [blame] | 1042 | uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1043 | { | 
 | 1044 |     uint32_t old = android_atomic_or(flags, &mTransactionFlags); | 
 | 1045 |     if ((old & flags)==0) { // wake the server up | 
| Mathias Agopian | bb64124 | 2010-05-18 17:06:55 -0700 | [diff] [blame] | 1046 |         signalEvent(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1047 |     } | 
 | 1048 |     return old; | 
 | 1049 | } | 
 | 1050 |  | 
 | 1051 | void SurfaceFlinger::openGlobalTransaction() | 
 | 1052 | { | 
 | 1053 |     android_atomic_inc(&mTransactionCount); | 
 | 1054 | } | 
 | 1055 |  | 
 | 1056 | void SurfaceFlinger::closeGlobalTransaction() | 
 | 1057 | { | 
 | 1058 |     if (android_atomic_dec(&mTransactionCount) == 1) { | 
 | 1059 |         signalEvent(); | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 1060 |  | 
 | 1061 |         // if there is a transaction with a resize, wait for it to  | 
 | 1062 |         // take effect before returning. | 
 | 1063 |         Mutex::Autolock _l(mStateLock); | 
 | 1064 |         while (mResizeTransationPending) { | 
| Mathias Agopian | 448f015 | 2009-09-30 14:42:13 -0700 | [diff] [blame] | 1065 |             status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); | 
 | 1066 |             if (CC_UNLIKELY(err != NO_ERROR)) { | 
 | 1067 |                 // just in case something goes wrong in SF, return to the | 
 | 1068 |                 // called after a few seconds. | 
 | 1069 |                 LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); | 
 | 1070 |                 mResizeTransationPending = false; | 
 | 1071 |                 break; | 
 | 1072 |             } | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 1073 |         } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1074 |     } | 
 | 1075 | } | 
 | 1076 |  | 
 | 1077 | status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags) | 
 | 1078 | { | 
 | 1079 |     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) | 
 | 1080 |         return BAD_VALUE; | 
 | 1081 |  | 
 | 1082 |     Mutex::Autolock _l(mStateLock); | 
 | 1083 |     mCurrentState.freezeDisplay = 1; | 
 | 1084 |     setTransactionFlags(eTransactionNeeded); | 
 | 1085 |  | 
 | 1086 |     // flags is intended to communicate some sort of animation behavior | 
| Mathias Agopian | 62b7444 | 2009-04-14 23:02:51 -0700 | [diff] [blame] | 1087 |     // (for instance fading) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1088 |     return NO_ERROR; | 
 | 1089 | } | 
 | 1090 |  | 
 | 1091 | status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags) | 
 | 1092 | { | 
 | 1093 |     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) | 
 | 1094 |         return BAD_VALUE; | 
 | 1095 |  | 
 | 1096 |     Mutex::Autolock _l(mStateLock); | 
 | 1097 |     mCurrentState.freezeDisplay = 0; | 
 | 1098 |     setTransactionFlags(eTransactionNeeded); | 
 | 1099 |  | 
 | 1100 |     // flags is intended to communicate some sort of animation behavior | 
| Mathias Agopian | 62b7444 | 2009-04-14 23:02:51 -0700 | [diff] [blame] | 1101 |     // (for instance fading) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1102 |     return NO_ERROR; | 
 | 1103 | } | 
 | 1104 |  | 
| Mathias Agopian | c08731e | 2009-03-27 18:11:38 -0700 | [diff] [blame] | 1105 | int SurfaceFlinger::setOrientation(DisplayID dpy,  | 
 | 1106 |         int orientation, uint32_t flags) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1107 | { | 
 | 1108 |     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) | 
 | 1109 |         return BAD_VALUE; | 
 | 1110 |  | 
 | 1111 |     Mutex::Autolock _l(mStateLock); | 
 | 1112 |     if (mCurrentState.orientation != orientation) { | 
 | 1113 |         if (uint32_t(orientation)<=eOrientation270 || orientation==42) { | 
| Mathias Agopian | c08731e | 2009-03-27 18:11:38 -0700 | [diff] [blame] | 1114 |             mCurrentState.orientationType = flags; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1115 |             mCurrentState.orientation = orientation; | 
 | 1116 |             setTransactionFlags(eTransactionNeeded); | 
 | 1117 |             mTransactionCV.wait(mStateLock); | 
 | 1118 |         } else { | 
 | 1119 |             orientation = BAD_VALUE; | 
 | 1120 |         } | 
 | 1121 |     } | 
 | 1122 |     return orientation; | 
 | 1123 | } | 
 | 1124 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1125 | sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid, | 
| Mathias Agopian | 7e27f05 | 2010-05-28 14:22:23 -0700 | [diff] [blame] | 1126 |         const String8& name, ISurfaceComposerClient::surface_data_t* params, | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1127 |         DisplayID d, uint32_t w, uint32_t h, PixelFormat format, | 
 | 1128 |         uint32_t flags) | 
 | 1129 | { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1130 |     sp<LayerBaseClient> layer; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1131 |     sp<LayerBaseClient::Surface> surfaceHandle; | 
| Mathias Agopian | 6e2d648 | 2009-07-09 18:16:43 -0700 | [diff] [blame] | 1132 |  | 
 | 1133 |     if (int32_t(w|h) < 0) { | 
 | 1134 |         LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)", | 
 | 1135 |                 int(w), int(h)); | 
 | 1136 |         return surfaceHandle; | 
 | 1137 |     } | 
 | 1138 |      | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1139 |     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h); | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1140 |     sp<Layer> normalLayer; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1141 |     switch (flags & eFXSurfaceMask) { | 
 | 1142 |         case eFXSurfaceNormal: | 
 | 1143 |             if (UNLIKELY(flags & ePushBuffers)) { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1144 |                 layer = createPushBuffersSurface(client, d, w, h, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1145 |             } else { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1146 |                 normalLayer = createNormalSurface(client, d, w, h, flags, format); | 
 | 1147 |                 layer = normalLayer; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1148 |             } | 
 | 1149 |             break; | 
 | 1150 |         case eFXSurfaceBlur: | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1151 |             layer = createBlurSurface(client, d, w, h, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1152 |             break; | 
 | 1153 |         case eFXSurfaceDim: | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1154 |             layer = createDimSurface(client, d, w, h, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1155 |             break; | 
 | 1156 |     } | 
 | 1157 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1158 |     if (layer != 0) { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1159 |         layer->initStates(w, h, flags); | 
| Mathias Agopian | 285dbde | 2010-03-01 16:09:43 -0800 | [diff] [blame] | 1160 |         layer->setName(name); | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1161 |         ssize_t token = addClientLayer(client, layer); | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1162 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1163 |         surfaceHandle = layer->getSurface(); | 
| Mathias Agopian | 1c97d2e | 2009-08-19 17:46:26 -0700 | [diff] [blame] | 1164 |         if (surfaceHandle != 0) {  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1165 |             params->token = token; | 
| Mathias Agopian | 1c97d2e | 2009-08-19 17:46:26 -0700 | [diff] [blame] | 1166 |             params->identity = surfaceHandle->getIdentity(); | 
 | 1167 |             params->width = w; | 
 | 1168 |             params->height = h; | 
 | 1169 |             params->format = format; | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1170 |             if (normalLayer != 0) { | 
 | 1171 |                 Mutex::Autolock _l(mStateLock); | 
 | 1172 |                 mLayerMap.add(surfaceHandle->asBinder(), normalLayer); | 
 | 1173 |             } | 
| Mathias Agopian | 1c97d2e | 2009-08-19 17:46:26 -0700 | [diff] [blame] | 1174 |         } | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1175 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1176 |         setTransactionFlags(eTransactionNeeded); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1177 |     } | 
 | 1178 |  | 
 | 1179 |     return surfaceHandle; | 
 | 1180 | } | 
 | 1181 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1182 | sp<Layer> SurfaceFlinger::createNormalSurface( | 
| Mathias Agopian | f9d9327 | 2009-06-19 17:00:27 -0700 | [diff] [blame] | 1183 |         const sp<Client>& client, DisplayID display, | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1184 |         uint32_t w, uint32_t h, uint32_t flags, | 
| Mathias Agopian | 1c97d2e | 2009-08-19 17:46:26 -0700 | [diff] [blame] | 1185 |         PixelFormat& format) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1186 | { | 
 | 1187 |     // initialize the surfaces | 
 | 1188 |     switch (format) { // TODO: take h/w into account | 
 | 1189 |     case PIXEL_FORMAT_TRANSPARENT: | 
 | 1190 |     case PIXEL_FORMAT_TRANSLUCENT: | 
 | 1191 |         format = PIXEL_FORMAT_RGBA_8888; | 
 | 1192 |         break; | 
 | 1193 |     case PIXEL_FORMAT_OPAQUE: | 
| Mathias Agopian | a8f3e4e | 2010-06-30 15:43:47 -0700 | [diff] [blame] | 1194 | #ifdef NO_RGBX_8888 | 
 | 1195 |         format = PIXEL_FORMAT_RGB_565; | 
 | 1196 | #else | 
| Mathias Agopian | 8f10540 | 2010-04-05 18:01:24 -0700 | [diff] [blame] | 1197 |         format = PIXEL_FORMAT_RGBX_8888; | 
| Mathias Agopian | a8f3e4e | 2010-06-30 15:43:47 -0700 | [diff] [blame] | 1198 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1199 |         break; | 
 | 1200 |     } | 
 | 1201 |  | 
| Mathias Agopian | a8f3e4e | 2010-06-30 15:43:47 -0700 | [diff] [blame] | 1202 | #ifdef NO_RGBX_8888 | 
 | 1203 |     if (format == PIXEL_FORMAT_RGBX_8888) | 
 | 1204 |         format = PIXEL_FORMAT_RGBA_8888; | 
 | 1205 | #endif | 
 | 1206 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1207 |     sp<Layer> layer = new Layer(this, display, client); | 
| Mathias Agopian | f9d9327 | 2009-06-19 17:00:27 -0700 | [diff] [blame] | 1208 |     status_t err = layer->setBuffers(w, h, format, flags); | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1209 |     if (LIKELY(err != NO_ERROR)) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1210 |         LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1211 |         layer.clear(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1212 |     } | 
 | 1213 |     return layer; | 
 | 1214 | } | 
 | 1215 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1216 | sp<LayerBlur> SurfaceFlinger::createBlurSurface( | 
| Mathias Agopian | f9d9327 | 2009-06-19 17:00:27 -0700 | [diff] [blame] | 1217 |         const sp<Client>& client, DisplayID display, | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1218 |         uint32_t w, uint32_t h, uint32_t flags) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1219 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1220 |     sp<LayerBlur> layer = new LayerBlur(this, display, client); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1221 |     layer->initStates(w, h, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1222 |     return layer; | 
 | 1223 | } | 
 | 1224 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1225 | sp<LayerDim> SurfaceFlinger::createDimSurface( | 
| Mathias Agopian | f9d9327 | 2009-06-19 17:00:27 -0700 | [diff] [blame] | 1226 |         const sp<Client>& client, DisplayID display, | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1227 |         uint32_t w, uint32_t h, uint32_t flags) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1228 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1229 |     sp<LayerDim> layer = new LayerDim(this, display, client); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1230 |     layer->initStates(w, h, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1231 |     return layer; | 
 | 1232 | } | 
 | 1233 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1234 | sp<LayerBuffer> SurfaceFlinger::createPushBuffersSurface( | 
| Mathias Agopian | f9d9327 | 2009-06-19 17:00:27 -0700 | [diff] [blame] | 1235 |         const sp<Client>& client, DisplayID display, | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1236 |         uint32_t w, uint32_t h, uint32_t flags) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1237 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1238 |     sp<LayerBuffer> layer = new LayerBuffer(this, display, client); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1239 |     layer->initStates(w, h, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1240 |     return layer; | 
 | 1241 | } | 
 | 1242 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1243 | status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1244 | { | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1245 |     /* | 
 | 1246 |      * called by the window manager, when a surface should be marked for | 
 | 1247 |      * destruction. | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 1248 |      *  | 
 | 1249 |      * The surface is removed from the current and drawing lists, but placed | 
 | 1250 |      * in the purgatory queue, so it's not destroyed right-away (we need | 
 | 1251 |      * to wait for all client's references to go away first). | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1252 |      */ | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1253 |  | 
| Mathias Agopian | 48d819a | 2009-09-10 19:41:18 -0700 | [diff] [blame] | 1254 |     status_t err = NAME_NOT_FOUND; | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 1255 |     Mutex::Autolock _l(mStateLock); | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1256 |     sp<LayerBaseClient> layer = client->getLayerUser(sid); | 
| Mathias Agopian | 48d819a | 2009-09-10 19:41:18 -0700 | [diff] [blame] | 1257 |     if (layer != 0) { | 
 | 1258 |         err = purgatorizeLayer_l(layer); | 
 | 1259 |         if (err == NO_ERROR) { | 
| Mathias Agopian | 48d819a | 2009-09-10 19:41:18 -0700 | [diff] [blame] | 1260 |             setTransactionFlags(eTransactionNeeded); | 
 | 1261 |         } | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1262 |     } | 
 | 1263 |     return err; | 
 | 1264 | } | 
 | 1265 |  | 
 | 1266 | status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) | 
 | 1267 | { | 
| Mathias Agopian | 759fdb2 | 2009-07-02 17:33:40 -0700 | [diff] [blame] | 1268 |     // called by ~ISurface() when all references are gone | 
| Mathias Agopian | 9a11206 | 2009-04-17 19:36:26 -0700 | [diff] [blame] | 1269 |      | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 1270 |     class MessageDestroySurface : public MessageBase { | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 1271 |         SurfaceFlinger* flinger; | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 1272 |         sp<LayerBaseClient> layer; | 
 | 1273 |     public: | 
| Mathias Agopian | 0aa758d | 2009-04-22 15:23:34 -0700 | [diff] [blame] | 1274 |         MessageDestroySurface( | 
 | 1275 |                 SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer) | 
 | 1276 |             : flinger(flinger), layer(layer) { } | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 1277 |         virtual bool handler() { | 
| Mathias Agopian | cd8c5e2 | 2009-06-19 16:24:02 -0700 | [diff] [blame] | 1278 |             sp<LayerBaseClient> l(layer); | 
 | 1279 |             layer.clear(); // clear it outside of the lock; | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 1280 |             Mutex::Autolock _l(flinger->mStateLock); | 
| Mathias Agopian | 759fdb2 | 2009-07-02 17:33:40 -0700 | [diff] [blame] | 1281 |             /* | 
 | 1282 |              * remove the layer from the current list -- chances are that it's  | 
 | 1283 |              * not in the list anyway, because it should have been removed  | 
 | 1284 |              * already upon request of the client (eg: window manager).  | 
 | 1285 |              * However, a buggy client could have not done that. | 
 | 1286 |              * Since we know we don't have any more clients, we don't need | 
 | 1287 |              * to use the purgatory. | 
 | 1288 |              */ | 
| Mathias Agopian | cd8c5e2 | 2009-06-19 16:24:02 -0700 | [diff] [blame] | 1289 |             status_t err = flinger->removeLayer_l(l); | 
| Mathias Agopian | 8c0a3d7 | 2009-09-23 16:44:00 -0700 | [diff] [blame] | 1290 |             LOGE_IF(err<0 && err != NAME_NOT_FOUND, | 
 | 1291 |                     "error removing layer=%p (%s)", l.get(), strerror(-err)); | 
| Mathias Agopian | f1d8e87 | 2009-04-20 19:39:12 -0700 | [diff] [blame] | 1292 |             return true; | 
 | 1293 |         } | 
 | 1294 |     }; | 
| Mathias Agopian | 3d57964 | 2009-06-04 18:46:21 -0700 | [diff] [blame] | 1295 |  | 
| Mathias Agopian | bb64124 | 2010-05-18 17:06:55 -0700 | [diff] [blame] | 1296 |     postMessageAsync( new MessageDestroySurface(this, layer) ); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1297 |     return NO_ERROR; | 
 | 1298 | } | 
 | 1299 |  | 
 | 1300 | status_t SurfaceFlinger::setClientState( | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1301 |         const sp<Client>& client, | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1302 |         int32_t count, | 
 | 1303 |         const layer_state_t* states) | 
 | 1304 | { | 
 | 1305 |     Mutex::Autolock _l(mStateLock); | 
 | 1306 |     uint32_t flags = 0; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1307 |     for (int i=0 ; i<count ; i++) { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 1308 |         const layer_state_t& s(states[i]); | 
 | 1309 |         sp<LayerBaseClient> layer(client->getLayerUser(s.surface)); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1310 |         if (layer != 0) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1311 |             const uint32_t what = s.what; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1312 |             if (what & ePositionChanged) { | 
 | 1313 |                 if (layer->setPosition(s.x, s.y)) | 
 | 1314 |                     flags |= eTraversalNeeded; | 
 | 1315 |             } | 
 | 1316 |             if (what & eLayerChanged) { | 
| Mathias Agopian | f6679fc | 2010-08-10 18:09:09 -0700 | [diff] [blame] | 1317 |                 ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1318 |                 if (layer->setLayer(s.z)) { | 
| Mathias Agopian | f6679fc | 2010-08-10 18:09:09 -0700 | [diff] [blame] | 1319 |                     mCurrentState.layersSortedByZ.removeAt(idx); | 
 | 1320 |                     mCurrentState.layersSortedByZ.add(layer); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1321 |                     // we need traversal (state changed) | 
 | 1322 |                     // AND transaction (list changed) | 
 | 1323 |                     flags |= eTransactionNeeded|eTraversalNeeded; | 
 | 1324 |                 } | 
 | 1325 |             } | 
 | 1326 |             if (what & eSizeChanged) { | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 1327 |                 if (layer->setSize(s.w, s.h)) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1328 |                     flags |= eTraversalNeeded; | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 1329 |                     mResizeTransationPending = true; | 
 | 1330 |                 } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1331 |             } | 
 | 1332 |             if (what & eAlphaChanged) { | 
 | 1333 |                 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) | 
 | 1334 |                     flags |= eTraversalNeeded; | 
 | 1335 |             } | 
 | 1336 |             if (what & eMatrixChanged) { | 
 | 1337 |                 if (layer->setMatrix(s.matrix)) | 
 | 1338 |                     flags |= eTraversalNeeded; | 
 | 1339 |             } | 
 | 1340 |             if (what & eTransparentRegionChanged) { | 
 | 1341 |                 if (layer->setTransparentRegionHint(s.transparentRegion)) | 
 | 1342 |                     flags |= eTraversalNeeded; | 
 | 1343 |             } | 
 | 1344 |             if (what & eVisibilityChanged) { | 
 | 1345 |                 if (layer->setFlags(s.flags, s.mask)) | 
 | 1346 |                     flags |= eTraversalNeeded; | 
 | 1347 |             } | 
 | 1348 |         } | 
 | 1349 |     } | 
 | 1350 |     if (flags) { | 
 | 1351 |         setTransactionFlags(flags); | 
 | 1352 |     } | 
 | 1353 |     return NO_ERROR; | 
 | 1354 | } | 
 | 1355 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1356 | void SurfaceFlinger::screenReleased(int dpy) | 
 | 1357 | { | 
 | 1358 |     // this may be called by a signal handler, we can't do too much in here | 
 | 1359 |     android_atomic_or(eConsoleReleased, &mConsoleSignals); | 
 | 1360 |     signalEvent(); | 
 | 1361 | } | 
 | 1362 |  | 
 | 1363 | void SurfaceFlinger::screenAcquired(int dpy) | 
 | 1364 | { | 
 | 1365 |     // this may be called by a signal handler, we can't do too much in here | 
 | 1366 |     android_atomic_or(eConsoleAcquired, &mConsoleSignals); | 
 | 1367 |     signalEvent(); | 
 | 1368 | } | 
 | 1369 |  | 
 | 1370 | status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) | 
 | 1371 | { | 
 | 1372 |     const size_t SIZE = 1024; | 
 | 1373 |     char buffer[SIZE]; | 
 | 1374 |     String8 result; | 
| Mathias Agopian | 375f563 | 2009-06-15 18:24:59 -0700 | [diff] [blame] | 1375 |     if (!mDump.checkCalling()) { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1376 |         snprintf(buffer, SIZE, "Permission Denial: " | 
 | 1377 |                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n", | 
 | 1378 |                 IPCThreadState::self()->getCallingPid(), | 
 | 1379 |                 IPCThreadState::self()->getCallingUid()); | 
 | 1380 |         result.append(buffer); | 
 | 1381 |     } else { | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 1382 |  | 
 | 1383 |         // figure out if we're stuck somewhere | 
 | 1384 |         const nsecs_t now = systemTime(); | 
 | 1385 |         const nsecs_t inSwapBuffers(mDebugInSwapBuffers); | 
 | 1386 |         const nsecs_t inTransaction(mDebugInTransaction); | 
 | 1387 |         nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0; | 
 | 1388 |         nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0; | 
 | 1389 |  | 
 | 1390 |         // Try to get the main lock, but don't insist if we can't | 
 | 1391 |         // (this would indicate SF is stuck, but we want to be able to | 
 | 1392 |         // print something in dumpsys). | 
 | 1393 |         int retry = 3; | 
 | 1394 |         while (mStateLock.tryLock()<0 && --retry>=0) { | 
 | 1395 |             usleep(1000000); | 
 | 1396 |         } | 
 | 1397 |         const bool locked(retry >= 0); | 
 | 1398 |         if (!locked) { | 
 | 1399 |             snprintf(buffer, SIZE,  | 
 | 1400 |                     "SurfaceFlinger appears to be unresponsive, " | 
 | 1401 |                     "dumping anyways (no locks held)\n"); | 
 | 1402 |             result.append(buffer); | 
 | 1403 |         } | 
 | 1404 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1405 |         const LayerVector& currentLayers = mCurrentState.layersSortedByZ; | 
 | 1406 |         const size_t count = currentLayers.size(); | 
 | 1407 |         for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | 1b5e102 | 2010-04-20 17:55:49 -0700 | [diff] [blame] | 1408 |             const sp<LayerBase>& layer(currentLayers[i]); | 
 | 1409 |             layer->dump(result, buffer, SIZE); | 
 | 1410 |             const Layer::State& s(layer->drawingState()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1411 |             s.transparentRegion.dump(result, "transparentRegion"); | 
 | 1412 |             layer->transparentRegionScreen.dump(result, "transparentRegionScreen"); | 
 | 1413 |             layer->visibleRegionScreen.dump(result, "visibleRegionScreen"); | 
 | 1414 |         } | 
| Mathias Agopian | 1b5e102 | 2010-04-20 17:55:49 -0700 | [diff] [blame] | 1415 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1416 |         mWormholeRegion.dump(result, "WormholeRegion"); | 
 | 1417 |         const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 1418 |         snprintf(buffer, SIZE, | 
 | 1419 |                 "  display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n", | 
 | 1420 |                 mFreezeDisplay?"yes":"no", mFreezeCount, | 
 | 1421 |                 mCurrentState.orientation, hw.canDraw()); | 
 | 1422 |         result.append(buffer); | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 1423 |         snprintf(buffer, SIZE, | 
 | 1424 |                 "  last eglSwapBuffers() time: %f us\n" | 
 | 1425 |                 "  last transaction time     : %f us\n", | 
 | 1426 |                 mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0); | 
 | 1427 |         result.append(buffer); | 
| Mathias Agopian | 1b5e102 | 2010-04-20 17:55:49 -0700 | [diff] [blame] | 1428 |  | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 1429 |         if (inSwapBuffersDuration || !locked) { | 
 | 1430 |             snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n", | 
 | 1431 |                     inSwapBuffersDuration/1000.0); | 
 | 1432 |             result.append(buffer); | 
 | 1433 |         } | 
| Mathias Agopian | 1b5e102 | 2010-04-20 17:55:49 -0700 | [diff] [blame] | 1434 |  | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 1435 |         if (inTransactionDuration || !locked) { | 
 | 1436 |             snprintf(buffer, SIZE, "  transaction time: %f us\n", | 
 | 1437 |                     inTransactionDuration/1000.0); | 
 | 1438 |             result.append(buffer); | 
 | 1439 |         } | 
| Mathias Agopian | 1b5e102 | 2010-04-20 17:55:49 -0700 | [diff] [blame] | 1440 |  | 
| Mathias Agopian | 3330b20 | 2009-10-05 17:07:12 -0700 | [diff] [blame] | 1441 |         const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 1442 |         alloc.dump(result); | 
| Mathias Agopian | 9795c42 | 2009-08-26 16:36:26 -0700 | [diff] [blame] | 1443 |  | 
 | 1444 |         if (locked) { | 
 | 1445 |             mStateLock.unlock(); | 
 | 1446 |         } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1447 |     } | 
 | 1448 |     write(fd, result.string(), result.size()); | 
 | 1449 |     return NO_ERROR; | 
 | 1450 | } | 
 | 1451 |  | 
 | 1452 | status_t SurfaceFlinger::onTransact( | 
 | 1453 |     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) | 
 | 1454 | { | 
 | 1455 |     switch (code) { | 
 | 1456 |         case CREATE_CONNECTION: | 
 | 1457 |         case OPEN_GLOBAL_TRANSACTION: | 
 | 1458 |         case CLOSE_GLOBAL_TRANSACTION: | 
 | 1459 |         case SET_ORIENTATION: | 
 | 1460 |         case FREEZE_DISPLAY: | 
 | 1461 |         case UNFREEZE_DISPLAY: | 
 | 1462 |         case BOOT_FINISHED: | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1463 |         case TURN_ELECTRON_BEAM_OFF: | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1464 |         case TURN_ELECTRON_BEAM_ON: | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1465 |         { | 
 | 1466 |             // codes that require permission check | 
 | 1467 |             IPCThreadState* ipc = IPCThreadState::self(); | 
 | 1468 |             const int pid = ipc->getCallingPid(); | 
| Mathias Agopian | a1ecca9 | 2009-05-21 19:21:59 -0700 | [diff] [blame] | 1469 |             const int uid = ipc->getCallingUid(); | 
| Mathias Agopian | 375f563 | 2009-06-15 18:24:59 -0700 | [diff] [blame] | 1470 |             if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) { | 
 | 1471 |                 LOGE("Permission Denial: " | 
 | 1472 |                         "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); | 
 | 1473 |                 return PERMISSION_DENIED; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1474 |             } | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 1475 |             break; | 
 | 1476 |         } | 
 | 1477 |         case CAPTURE_SCREEN: | 
 | 1478 |         { | 
 | 1479 |             // codes that require permission check | 
 | 1480 |             IPCThreadState* ipc = IPCThreadState::self(); | 
 | 1481 |             const int pid = ipc->getCallingPid(); | 
 | 1482 |             const int uid = ipc->getCallingUid(); | 
 | 1483 |             if ((uid != AID_GRAPHICS) && !mReadFramebuffer.check(pid, uid)) { | 
 | 1484 |                 LOGE("Permission Denial: " | 
 | 1485 |                         "can't read framebuffer pid=%d, uid=%d", pid, uid); | 
 | 1486 |                 return PERMISSION_DENIED; | 
 | 1487 |             } | 
 | 1488 |             break; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1489 |         } | 
 | 1490 |     } | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 1491 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1492 |     status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); | 
 | 1493 |     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { | 
| Mathias Agopian | b8a5560 | 2009-06-26 19:06:36 -0700 | [diff] [blame] | 1494 |         CHECK_INTERFACE(ISurfaceComposer, data, reply); | 
| Mathias Agopian | 375f563 | 2009-06-15 18:24:59 -0700 | [diff] [blame] | 1495 |         if (UNLIKELY(!mHardwareTest.checkCalling())) { | 
 | 1496 |             IPCThreadState* ipc = IPCThreadState::self(); | 
 | 1497 |             const int pid = ipc->getCallingPid(); | 
 | 1498 |             const int uid = ipc->getCallingUid(); | 
 | 1499 |             LOGE("Permission Denial: " | 
 | 1500 |                     "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1501 |             return PERMISSION_DENIED; | 
 | 1502 |         } | 
 | 1503 |         int n; | 
 | 1504 |         switch (code) { | 
| Mathias Agopian | 01b7668 | 2009-04-16 20:04:08 -0700 | [diff] [blame] | 1505 |             case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 1506 |             case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1507 |                 return NO_ERROR; | 
 | 1508 |             case 1002:  // SHOW_UPDATES | 
 | 1509 |                 n = data.readInt32(); | 
 | 1510 |                 mDebugRegion = n ? n : (mDebugRegion ? 0 : 1); | 
 | 1511 |                 return NO_ERROR; | 
 | 1512 |             case 1003:  // SHOW_BACKGROUND | 
 | 1513 |                 n = data.readInt32(); | 
 | 1514 |                 mDebugBackground = n ? 1 : 0; | 
 | 1515 |                 return NO_ERROR; | 
 | 1516 |             case 1004:{ // repaint everything | 
 | 1517 |                 Mutex::Autolock _l(mStateLock); | 
 | 1518 |                 const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 1519 |                 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe | 
 | 1520 |                 signalEvent(); | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 1521 |                 return NO_ERROR; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1522 |             } | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 1523 |             case 1005:{ // force transaction | 
 | 1524 |                 setTransactionFlags(eTransactionNeeded|eTraversalNeeded); | 
 | 1525 |                 return NO_ERROR; | 
 | 1526 |             } | 
| Mathias Agopian | 35b48d1 | 2010-09-13 22:57:58 -0700 | [diff] [blame] | 1527 |             case 1006:{ // enable/disable GraphicLog | 
 | 1528 |                 int enabled = data.readInt32(); | 
 | 1529 |                 GraphicLog::getInstance().setEnabled(enabled); | 
 | 1530 |                 return NO_ERROR; | 
 | 1531 |             } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1532 |             case 1007: // set mFreezeCount | 
 | 1533 |                 mFreezeCount = data.readInt32(); | 
| Mathias Agopian | 0408772 | 2009-12-01 17:23:28 -0800 | [diff] [blame] | 1534 |                 mFreezeDisplayTime = 0; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1535 |                 return NO_ERROR; | 
 | 1536 |             case 1010:  // interrogate. | 
| Mathias Agopian | 01b7668 | 2009-04-16 20:04:08 -0700 | [diff] [blame] | 1537 |                 reply->writeInt32(0); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1538 |                 reply->writeInt32(0); | 
 | 1539 |                 reply->writeInt32(mDebugRegion); | 
 | 1540 |                 reply->writeInt32(mDebugBackground); | 
 | 1541 |                 return NO_ERROR; | 
 | 1542 |             case 1013: { | 
 | 1543 |                 Mutex::Autolock _l(mStateLock); | 
 | 1544 |                 const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 1545 |                 reply->writeInt32(hw.getPageFlipCount()); | 
 | 1546 |             } | 
 | 1547 |             return NO_ERROR; | 
 | 1548 |         } | 
 | 1549 |     } | 
 | 1550 |     return err; | 
 | 1551 | } | 
 | 1552 |  | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1553 | // --------------------------------------------------------------------------- | 
 | 1554 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1555 | status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy, | 
 | 1556 |         GLuint* textureName, GLfloat* uOut, GLfloat* vOut) | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1557 | { | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1558 |     if (!GLExtensions::getInstance().haveFramebufferObject()) | 
 | 1559 |         return INVALID_OPERATION; | 
 | 1560 |  | 
 | 1561 |     // get screen geometry | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1562 |     const DisplayHardware& hw(graphicPlane(dpy).displayHardware()); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1563 |     const uint32_t hw_w = hw.getWidth(); | 
 | 1564 |     const uint32_t hw_h = hw.getHeight(); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1565 |     GLfloat u = 1; | 
 | 1566 |     GLfloat v = 1; | 
 | 1567 |  | 
 | 1568 |     // make sure to clear all GL error flags | 
 | 1569 |     while ( glGetError() != GL_NO_ERROR ) ; | 
 | 1570 |  | 
 | 1571 |     // create a FBO | 
 | 1572 |     GLuint name, tname; | 
 | 1573 |     glGenTextures(1, &tname); | 
 | 1574 |     glBindTexture(GL_TEXTURE_2D, tname); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1575 |     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, | 
 | 1576 |             hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1577 |     if (glGetError() != GL_NO_ERROR) { | 
| Mathias Agopian | 015fb3f | 2010-10-14 12:19:37 -0700 | [diff] [blame] | 1578 |         while ( glGetError() != GL_NO_ERROR ) ; | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1579 |         GLint tw = (2 << (31 - clz(hw_w))); | 
 | 1580 |         GLint th = (2 << (31 - clz(hw_h))); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1581 |         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, | 
 | 1582 |                 tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1583 |         u = GLfloat(hw_w) / tw; | 
 | 1584 |         v = GLfloat(hw_h) / th; | 
 | 1585 |     } | 
 | 1586 |     glGenFramebuffersOES(1, &name); | 
 | 1587 |     glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1588 |     glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, | 
 | 1589 |             GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1590 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1591 |     // redraw the screen entirely... | 
 | 1592 |     glClearColor(0,0,0,1); | 
 | 1593 |     glClear(GL_COLOR_BUFFER_BIT); | 
 | 1594 |     const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); | 
 | 1595 |     const size_t count = layers.size(); | 
 | 1596 |     for (size_t i=0 ; i<count ; ++i) { | 
 | 1597 |         const sp<LayerBase>& layer(layers[i]); | 
 | 1598 |         layer->drawForSreenShot(); | 
 | 1599 |     } | 
 | 1600 |  | 
 | 1601 |     // back to main framebuffer | 
 | 1602 |     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | 
 | 1603 |     glDisable(GL_SCISSOR_TEST); | 
 | 1604 |     glDeleteFramebuffersOES(1, &name); | 
 | 1605 |  | 
 | 1606 |     *textureName = tname; | 
 | 1607 |     *uOut = u; | 
 | 1608 |     *vOut = v; | 
 | 1609 |     return NO_ERROR; | 
 | 1610 | } | 
 | 1611 |  | 
 | 1612 | // --------------------------------------------------------------------------- | 
 | 1613 |  | 
 | 1614 | status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() | 
 | 1615 | { | 
 | 1616 |     status_t result = PERMISSION_DENIED; | 
 | 1617 |  | 
 | 1618 |     if (!GLExtensions::getInstance().haveFramebufferObject()) | 
 | 1619 |         return INVALID_OPERATION; | 
 | 1620 |  | 
 | 1621 |     // get screen geometry | 
 | 1622 |     const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 1623 |     const uint32_t hw_w = hw.getWidth(); | 
 | 1624 |     const uint32_t hw_h = hw.getHeight(); | 
 | 1625 |     const Region screenBounds(hw.bounds()); | 
 | 1626 |  | 
 | 1627 |     GLfloat u, v; | 
 | 1628 |     GLuint tname; | 
 | 1629 |     result = renderScreenToTextureLocked(0, &tname, &u, &v); | 
 | 1630 |     if (result != NO_ERROR) { | 
 | 1631 |         return result; | 
 | 1632 |     } | 
 | 1633 |  | 
 | 1634 |     GLfloat vtx[8]; | 
 | 1635 |     const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; | 
 | 1636 |     glEnable(GL_TEXTURE_2D); | 
 | 1637 |     glBindTexture(GL_TEXTURE_2D, tname); | 
 | 1638 |     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | 
 | 1639 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
 | 1640 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
 | 1641 |     glTexCoordPointer(2, GL_FLOAT, 0, texCoords); | 
 | 1642 |     glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 
 | 1643 |     glVertexPointer(2, GL_FLOAT, 0, vtx); | 
 | 1644 |  | 
 | 1645 |     class s_curve_interpolator { | 
 | 1646 |         const float nbFrames, s, v; | 
 | 1647 |     public: | 
 | 1648 |         s_curve_interpolator(int nbFrames, float s) | 
 | 1649 |         : nbFrames(1.0f / (nbFrames-1)), s(s), | 
 | 1650 |           v(1.0f + expf(-s + 0.5f*s)) { | 
 | 1651 |         } | 
 | 1652 |         float operator()(int f) { | 
 | 1653 |             const float x = f * nbFrames; | 
 | 1654 |             return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f; | 
 | 1655 |         } | 
 | 1656 |     }; | 
 | 1657 |  | 
 | 1658 |     class v_stretch { | 
 | 1659 |         const GLfloat hw_w, hw_h; | 
 | 1660 |     public: | 
 | 1661 |         v_stretch(uint32_t hw_w, uint32_t hw_h) | 
 | 1662 |         : hw_w(hw_w), hw_h(hw_h) { | 
 | 1663 |         } | 
 | 1664 |         void operator()(GLfloat* vtx, float v) { | 
 | 1665 |             const GLfloat w = hw_w + (hw_w * v); | 
 | 1666 |             const GLfloat h = hw_h - (hw_h * v); | 
 | 1667 |             const GLfloat x = (hw_w - w) * 0.5f; | 
 | 1668 |             const GLfloat y = (hw_h - h) * 0.5f; | 
 | 1669 |             vtx[0] = x;         vtx[1] = y; | 
 | 1670 |             vtx[2] = x;         vtx[3] = y + h; | 
 | 1671 |             vtx[4] = x + w;     vtx[5] = y + h; | 
 | 1672 |             vtx[6] = x + w;     vtx[7] = y; | 
 | 1673 |         } | 
 | 1674 |     }; | 
 | 1675 |  | 
 | 1676 |     class h_stretch { | 
 | 1677 |         const GLfloat hw_w, hw_h; | 
 | 1678 |     public: | 
 | 1679 |         h_stretch(uint32_t hw_w, uint32_t hw_h) | 
 | 1680 |         : hw_w(hw_w), hw_h(hw_h) { | 
 | 1681 |         } | 
 | 1682 |         void operator()(GLfloat* vtx, float v) { | 
 | 1683 |             const GLfloat w = hw_w - (hw_w * v); | 
 | 1684 |             const GLfloat h = 1.0f; | 
 | 1685 |             const GLfloat x = (hw_w - w) * 0.5f; | 
 | 1686 |             const GLfloat y = (hw_h - h) * 0.5f; | 
 | 1687 |             vtx[0] = x;         vtx[1] = y; | 
 | 1688 |             vtx[2] = x;         vtx[3] = y + h; | 
 | 1689 |             vtx[4] = x + w;     vtx[5] = y + h; | 
 | 1690 |             vtx[6] = x + w;     vtx[7] = y; | 
 | 1691 |         } | 
 | 1692 |     }; | 
 | 1693 |  | 
 | 1694 |     // the full animation is 24 frames | 
 | 1695 |     const int nbFrames = 12; | 
 | 1696 |     s_curve_interpolator itr(nbFrames, 7.5f); | 
 | 1697 |     s_curve_interpolator itg(nbFrames, 8.0f); | 
 | 1698 |     s_curve_interpolator itb(nbFrames, 8.5f); | 
 | 1699 |  | 
 | 1700 |     v_stretch vverts(hw_w, hw_h); | 
 | 1701 |     glEnable(GL_BLEND); | 
 | 1702 |     glBlendFunc(GL_ONE, GL_ONE); | 
 | 1703 |     for (int i=0 ; i<nbFrames ; i++) { | 
 | 1704 |         float x, y, w, h; | 
 | 1705 |         const float vr = itr(i); | 
 | 1706 |         const float vg = itg(i); | 
 | 1707 |         const float vb = itb(i); | 
 | 1708 |  | 
 | 1709 |         // clear screen | 
 | 1710 |         glColorMask(1,1,1,1); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1711 |         glClear(GL_COLOR_BUFFER_BIT); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1712 |         glEnable(GL_TEXTURE_2D); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1713 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1714 |         // draw the red plane | 
 | 1715 |         vverts(vtx, vr); | 
 | 1716 |         glColorMask(1,0,0,1); | 
 | 1717 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1718 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1719 |         // draw the green plane | 
 | 1720 |         vverts(vtx, vg); | 
 | 1721 |         glColorMask(0,1,0,1); | 
 | 1722 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1723 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1724 |         // draw the blue plane | 
 | 1725 |         vverts(vtx, vb); | 
 | 1726 |         glColorMask(0,0,1,1); | 
 | 1727 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1728 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1729 |         // draw the white highlight (we use the last vertices) | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1730 |         glDisable(GL_TEXTURE_2D); | 
 | 1731 |         glColorMask(1,1,1,1); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1732 |         glColor4f(vg, vg, vg, 1); | 
 | 1733 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 1734 |         hw.flip(screenBounds); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1735 |     } | 
 | 1736 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1737 |     h_stretch hverts(hw_w, hw_h); | 
 | 1738 |     glDisable(GL_BLEND); | 
 | 1739 |     glDisable(GL_TEXTURE_2D); | 
 | 1740 |     glColorMask(1,1,1,1); | 
 | 1741 |     for (int i=0 ; i<nbFrames ; i++) { | 
 | 1742 |         const float v = itg(i); | 
 | 1743 |         hverts(vtx, v); | 
 | 1744 |         glClear(GL_COLOR_BUFFER_BIT); | 
 | 1745 |         glColor4f(1-v, 1-v, 1-v, 1); | 
 | 1746 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 1747 |         hw.flip(screenBounds); | 
 | 1748 |     } | 
 | 1749 |  | 
 | 1750 |     glColorMask(1,1,1,1); | 
 | 1751 |     glEnable(GL_SCISSOR_TEST); | 
 | 1752 |     glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 
 | 1753 |     glDeleteTextures(1, &tname); | 
 | 1754 |     return NO_ERROR; | 
 | 1755 | } | 
 | 1756 |  | 
 | 1757 | status_t SurfaceFlinger::electronBeamOnAnimationImplLocked() | 
 | 1758 | { | 
 | 1759 |     status_t result = PERMISSION_DENIED; | 
 | 1760 |  | 
 | 1761 |     if (!GLExtensions::getInstance().haveFramebufferObject()) | 
 | 1762 |         return INVALID_OPERATION; | 
 | 1763 |  | 
 | 1764 |  | 
 | 1765 |     // get screen geometry | 
 | 1766 |     const DisplayHardware& hw(graphicPlane(0).displayHardware()); | 
 | 1767 |     const uint32_t hw_w = hw.getWidth(); | 
 | 1768 |     const uint32_t hw_h = hw.getHeight(); | 
 | 1769 |     const Region screenBounds(hw.bounds()); | 
 | 1770 |  | 
 | 1771 |     GLfloat u, v; | 
 | 1772 |     GLuint tname; | 
 | 1773 |     result = renderScreenToTextureLocked(0, &tname, &u, &v); | 
 | 1774 |     if (result != NO_ERROR) { | 
 | 1775 |         return result; | 
 | 1776 |     } | 
 | 1777 |  | 
 | 1778 |     // back to main framebuffer | 
 | 1779 |     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | 
 | 1780 |     glDisable(GL_SCISSOR_TEST); | 
 | 1781 |  | 
 | 1782 |     GLfloat vtx[8]; | 
 | 1783 |     const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; | 
 | 1784 |     glEnable(GL_TEXTURE_2D); | 
 | 1785 |     glBindTexture(GL_TEXTURE_2D, tname); | 
 | 1786 |     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 
 | 1787 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
 | 1788 |     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
 | 1789 |     glTexCoordPointer(2, GL_FLOAT, 0, texCoords); | 
 | 1790 |     glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 
 | 1791 |     glVertexPointer(2, GL_FLOAT, 0, vtx); | 
 | 1792 |  | 
 | 1793 |     class s_curve_interpolator { | 
 | 1794 |         const float nbFrames, s, v; | 
 | 1795 |     public: | 
 | 1796 |         s_curve_interpolator(int nbFrames, float s) | 
 | 1797 |         : nbFrames(1.0f / (nbFrames-1)), s(s), | 
 | 1798 |           v(1.0f + expf(-s + 0.5f*s)) { | 
 | 1799 |         } | 
 | 1800 |         float operator()(int f) { | 
 | 1801 |             const float x = f * nbFrames; | 
 | 1802 |             return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f; | 
 | 1803 |         } | 
 | 1804 |     }; | 
 | 1805 |  | 
 | 1806 |     class v_stretch { | 
 | 1807 |         const GLfloat hw_w, hw_h; | 
 | 1808 |     public: | 
 | 1809 |         v_stretch(uint32_t hw_w, uint32_t hw_h) | 
 | 1810 |         : hw_w(hw_w), hw_h(hw_h) { | 
 | 1811 |         } | 
 | 1812 |         void operator()(GLfloat* vtx, float v) { | 
 | 1813 |             const GLfloat w = hw_w + (hw_w * v); | 
 | 1814 |             const GLfloat h = hw_h - (hw_h * v); | 
 | 1815 |             const GLfloat x = (hw_w - w) * 0.5f; | 
 | 1816 |             const GLfloat y = (hw_h - h) * 0.5f; | 
 | 1817 |             vtx[0] = x;         vtx[1] = y; | 
 | 1818 |             vtx[2] = x;         vtx[3] = y + h; | 
 | 1819 |             vtx[4] = x + w;     vtx[5] = y + h; | 
 | 1820 |             vtx[6] = x + w;     vtx[7] = y; | 
 | 1821 |         } | 
 | 1822 |     }; | 
 | 1823 |  | 
 | 1824 |     class h_stretch { | 
 | 1825 |         const GLfloat hw_w, hw_h; | 
 | 1826 |     public: | 
 | 1827 |         h_stretch(uint32_t hw_w, uint32_t hw_h) | 
 | 1828 |         : hw_w(hw_w), hw_h(hw_h) { | 
 | 1829 |         } | 
 | 1830 |         void operator()(GLfloat* vtx, float v) { | 
 | 1831 |             const GLfloat w = hw_w - (hw_w * v); | 
 | 1832 |             const GLfloat h = 1.0f; | 
 | 1833 |             const GLfloat x = (hw_w - w) * 0.5f; | 
 | 1834 |             const GLfloat y = (hw_h - h) * 0.5f; | 
 | 1835 |             vtx[0] = x;         vtx[1] = y; | 
 | 1836 |             vtx[2] = x;         vtx[3] = y + h; | 
 | 1837 |             vtx[4] = x + w;     vtx[5] = y + h; | 
 | 1838 |             vtx[6] = x + w;     vtx[7] = y; | 
 | 1839 |         } | 
 | 1840 |     }; | 
 | 1841 |  | 
| Mathias Agopian | a6546e5 | 2010-10-14 12:33:07 -0700 | [diff] [blame] | 1842 |     // the full animation is 12 frames | 
 | 1843 |     int nbFrames = 8; | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1844 |     s_curve_interpolator itr(nbFrames, 7.5f); | 
 | 1845 |     s_curve_interpolator itg(nbFrames, 8.0f); | 
 | 1846 |     s_curve_interpolator itb(nbFrames, 8.5f); | 
 | 1847 |  | 
 | 1848 |     h_stretch hverts(hw_w, hw_h); | 
 | 1849 |     glDisable(GL_BLEND); | 
 | 1850 |     glDisable(GL_TEXTURE_2D); | 
 | 1851 |     glColorMask(1,1,1,1); | 
 | 1852 |     for (int i=nbFrames-1 ; i>=0 ; i--) { | 
 | 1853 |         const float v = itg(i); | 
 | 1854 |         hverts(vtx, v); | 
 | 1855 |         glClear(GL_COLOR_BUFFER_BIT); | 
 | 1856 |         glColor4f(1-v, 1-v, 1-v, 1); | 
 | 1857 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 1858 |         hw.flip(screenBounds); | 
 | 1859 |     } | 
 | 1860 |  | 
| Mathias Agopian | a6546e5 | 2010-10-14 12:33:07 -0700 | [diff] [blame] | 1861 |     nbFrames = 4; | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1862 |     v_stretch vverts(hw_w, hw_h); | 
 | 1863 |     glEnable(GL_BLEND); | 
 | 1864 |     glBlendFunc(GL_ONE, GL_ONE); | 
 | 1865 |     for (int i=nbFrames-1 ; i>=0 ; i--) { | 
 | 1866 |         float x, y, w, h; | 
 | 1867 |         const float vr = itr(i); | 
 | 1868 |         const float vg = itg(i); | 
 | 1869 |         const float vb = itb(i); | 
 | 1870 |  | 
 | 1871 |         // clear screen | 
 | 1872 |         glColorMask(1,1,1,1); | 
 | 1873 |         glClear(GL_COLOR_BUFFER_BIT); | 
 | 1874 |         glEnable(GL_TEXTURE_2D); | 
 | 1875 |  | 
 | 1876 |         // draw the red plane | 
 | 1877 |         vverts(vtx, vr); | 
 | 1878 |         glColorMask(1,0,0,1); | 
 | 1879 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 1880 |  | 
 | 1881 |         // draw the green plane | 
 | 1882 |         vverts(vtx, vg); | 
 | 1883 |         glColorMask(0,1,0,1); | 
 | 1884 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 1885 |  | 
 | 1886 |         // draw the blue plane | 
 | 1887 |         vverts(vtx, vb); | 
 | 1888 |         glColorMask(0,0,1,1); | 
 | 1889 |         glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
 | 1890 |  | 
 | 1891 |         hw.flip(screenBounds); | 
 | 1892 |     } | 
 | 1893 |  | 
 | 1894 |     glColorMask(1,1,1,1); | 
 | 1895 |     glEnable(GL_SCISSOR_TEST); | 
 | 1896 |     glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1897 |     glDeleteTextures(1, &tname); | 
 | 1898 |  | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1899 |     return NO_ERROR; | 
 | 1900 | } | 
 | 1901 |  | 
 | 1902 | // --------------------------------------------------------------------------- | 
 | 1903 |  | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1904 | status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode) | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1905 | { | 
 | 1906 |     DisplayHardware& hw(graphicPlane(0).editDisplayHardware()); | 
 | 1907 |     if (!hw.canDraw()) { | 
 | 1908 |         // we're already off | 
 | 1909 |         return NO_ERROR; | 
 | 1910 |     } | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1911 |     if (mode & ISurfaceComposer::eElectronBeamAnimationOff) { | 
 | 1912 |         electronBeamOffAnimationImplLocked(); | 
 | 1913 |     } | 
 | 1914 |  | 
 | 1915 |     // always clear the whole screen at the end of the animation | 
 | 1916 |     glClearColor(0,0,0,1); | 
 | 1917 |     glDisable(GL_SCISSOR_TEST); | 
 | 1918 |     glClear(GL_COLOR_BUFFER_BIT); | 
 | 1919 |     glEnable(GL_SCISSOR_TEST); | 
 | 1920 |     hw.flip( Region(hw.bounds()) ); | 
 | 1921 |  | 
| Mathias Agopian | 015fb3f | 2010-10-14 12:19:37 -0700 | [diff] [blame] | 1922 |     hw.setCanDraw(false); | 
 | 1923 |     return NO_ERROR; | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1924 | } | 
 | 1925 |  | 
 | 1926 | status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode) | 
 | 1927 | { | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1928 |     class MessageTurnElectronBeamOff : public MessageBase { | 
 | 1929 |         SurfaceFlinger* flinger; | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1930 |         int32_t mode; | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1931 |         status_t result; | 
 | 1932 |     public: | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1933 |         MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode) | 
 | 1934 |             : flinger(flinger), mode(mode), result(PERMISSION_DENIED) { | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1935 |         } | 
 | 1936 |         status_t getResult() const { | 
 | 1937 |             return result; | 
 | 1938 |         } | 
 | 1939 |         virtual bool handler() { | 
 | 1940 |             Mutex::Autolock _l(flinger->mStateLock); | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1941 |             result = flinger->turnElectronBeamOffImplLocked(mode); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1942 |             return true; | 
 | 1943 |         } | 
 | 1944 |     }; | 
 | 1945 |  | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1946 |     sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode); | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1947 |     status_t res = postMessageSync(msg); | 
 | 1948 |     if (res == NO_ERROR) { | 
 | 1949 |         res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult(); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1950 |  | 
 | 1951 |         // work-around: when the power-manager calls us we activate the | 
 | 1952 |         // animation. eventually, the "on" animation will be called | 
 | 1953 |         // by the power-manager itself | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1954 |         mElectronBeamAnimationMode = mode; | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 1955 |     } | 
 | 1956 |     return res; | 
 | 1957 | } | 
 | 1958 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1959 | // --------------------------------------------------------------------------- | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 1960 |  | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1961 | status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode) | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1962 | { | 
 | 1963 |     DisplayHardware& hw(graphicPlane(0).editDisplayHardware()); | 
 | 1964 |     if (hw.canDraw()) { | 
 | 1965 |         // we're already on | 
 | 1966 |         return NO_ERROR; | 
 | 1967 |     } | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1968 |     if (mode & ISurfaceComposer::eElectronBeamAnimationOn) { | 
 | 1969 |         electronBeamOnAnimationImplLocked(); | 
 | 1970 |     } | 
| Mathias Agopian | 015fb3f | 2010-10-14 12:19:37 -0700 | [diff] [blame] | 1971 |     hw.setCanDraw(true); | 
| Mathias Agopian | a7f0373 | 2010-10-14 12:46:24 -0700 | [diff] [blame] | 1972 |  | 
 | 1973 |     // make sure to redraw the whole screen when the animation is done | 
 | 1974 |     mDirtyRegion.set(hw.bounds()); | 
 | 1975 |     signalEvent(); | 
 | 1976 |  | 
| Mathias Agopian | 015fb3f | 2010-10-14 12:19:37 -0700 | [diff] [blame] | 1977 |     return NO_ERROR; | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1978 | } | 
 | 1979 |  | 
 | 1980 | status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode) | 
 | 1981 | { | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1982 |     class MessageTurnElectronBeamOn : public MessageBase { | 
 | 1983 |         SurfaceFlinger* flinger; | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1984 |         int32_t mode; | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1985 |         status_t result; | 
 | 1986 |     public: | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1987 |         MessageTurnElectronBeamOn(SurfaceFlinger* flinger, int32_t mode) | 
 | 1988 |             : flinger(flinger), mode(mode), result(PERMISSION_DENIED) { | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1989 |         } | 
 | 1990 |         status_t getResult() const { | 
 | 1991 |             return result; | 
 | 1992 |         } | 
 | 1993 |         virtual bool handler() { | 
 | 1994 |             Mutex::Autolock _l(flinger->mStateLock); | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 1995 |             result = flinger->turnElectronBeamOnImplLocked(mode); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 1996 |             return true; | 
 | 1997 |         } | 
 | 1998 |     }; | 
 | 1999 |  | 
| Mathias Agopian | abd671a | 2010-10-14 14:54:06 -0700 | [diff] [blame] | 2000 |     postMessageAsync( new MessageTurnElectronBeamOn(this, mode) ); | 
| Mathias Agopian | 9daa5c9 | 2010-10-12 16:05:48 -0700 | [diff] [blame] | 2001 |     return NO_ERROR; | 
 | 2002 | } | 
 | 2003 |  | 
 | 2004 | // --------------------------------------------------------------------------- | 
 | 2005 |  | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2006 | status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, | 
 | 2007 |         sp<IMemoryHeap>* heap, | 
 | 2008 |         uint32_t* w, uint32_t* h, PixelFormat* f, | 
 | 2009 |         uint32_t sw, uint32_t sh) | 
 | 2010 | { | 
 | 2011 |     status_t result = PERMISSION_DENIED; | 
 | 2012 |  | 
 | 2013 |     // only one display supported for now | 
 | 2014 |     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) | 
 | 2015 |         return BAD_VALUE; | 
 | 2016 |  | 
 | 2017 |     if (!GLExtensions::getInstance().haveFramebufferObject()) | 
 | 2018 |         return INVALID_OPERATION; | 
 | 2019 |  | 
 | 2020 |     // get screen geometry | 
 | 2021 |     const DisplayHardware& hw(graphicPlane(dpy).displayHardware()); | 
 | 2022 |     const uint32_t hw_w = hw.getWidth(); | 
 | 2023 |     const uint32_t hw_h = hw.getHeight(); | 
 | 2024 |  | 
 | 2025 |     if ((sw > hw_w) || (sh > hw_h)) | 
 | 2026 |         return BAD_VALUE; | 
 | 2027 |  | 
 | 2028 |     sw = (!sw) ? hw_w : sw; | 
 | 2029 |     sh = (!sh) ? hw_h : sh; | 
 | 2030 |     const size_t size = sw * sh * 4; | 
 | 2031 |  | 
 | 2032 |     // make sure to clear all GL error flags | 
 | 2033 |     while ( glGetError() != GL_NO_ERROR ) ; | 
 | 2034 |  | 
 | 2035 |     // create a FBO | 
 | 2036 |     GLuint name, tname; | 
 | 2037 |     glGenRenderbuffersOES(1, &tname); | 
 | 2038 |     glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname); | 
 | 2039 |     glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh); | 
 | 2040 |     glGenFramebuffersOES(1, &name); | 
 | 2041 |     glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); | 
 | 2042 |     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, | 
 | 2043 |             GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname); | 
 | 2044 |  | 
 | 2045 |     GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); | 
 | 2046 |     if (status == GL_FRAMEBUFFER_COMPLETE_OES) { | 
 | 2047 |  | 
 | 2048 |         // invert everything, b/c glReadPixel() below will invert the FB | 
 | 2049 |         glViewport(0, 0, sw, sh); | 
 | 2050 |         glMatrixMode(GL_PROJECTION); | 
 | 2051 |         glPushMatrix(); | 
 | 2052 |         glLoadIdentity(); | 
 | 2053 |         glOrthof(0, hw_w, 0, hw_h, 0, 1); | 
 | 2054 |         glMatrixMode(GL_MODELVIEW); | 
 | 2055 |  | 
 | 2056 |         // redraw the screen entirely... | 
 | 2057 |         glClearColor(0,0,0,1); | 
 | 2058 |         glClear(GL_COLOR_BUFFER_BIT); | 
 | 2059 |         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); | 
 | 2060 |         const size_t count = layers.size(); | 
 | 2061 |         for (size_t i=0 ; i<count ; ++i) { | 
 | 2062 |             const sp<LayerBase>& layer(layers[i]); | 
 | 2063 |             layer->drawForSreenShot(); | 
 | 2064 |         } | 
 | 2065 |  | 
 | 2066 |         // XXX: this is needed on tegra | 
 | 2067 |         glScissor(0, 0, sw, sh); | 
 | 2068 |  | 
 | 2069 |         // check for errors and return screen capture | 
 | 2070 |         if (glGetError() != GL_NO_ERROR) { | 
 | 2071 |             // error while rendering | 
 | 2072 |             result = INVALID_OPERATION; | 
 | 2073 |         } else { | 
 | 2074 |             // allocate shared memory large enough to hold the | 
 | 2075 |             // screen capture | 
 | 2076 |             sp<MemoryHeapBase> base( | 
 | 2077 |                     new MemoryHeapBase(size, 0, "screen-capture") ); | 
 | 2078 |             void* const ptr = base->getBase(); | 
 | 2079 |             if (ptr) { | 
 | 2080 |                 // capture the screen with glReadPixels() | 
 | 2081 |                 glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr); | 
 | 2082 |                 if (glGetError() == GL_NO_ERROR) { | 
 | 2083 |                     *heap = base; | 
 | 2084 |                     *w = sw; | 
 | 2085 |                     *h = sh; | 
 | 2086 |                     *f = PIXEL_FORMAT_RGBA_8888; | 
 | 2087 |                     result = NO_ERROR; | 
 | 2088 |                 } | 
 | 2089 |             } else { | 
 | 2090 |                 result = NO_MEMORY; | 
 | 2091 |             } | 
 | 2092 |         } | 
 | 2093 |  | 
 | 2094 |         glEnable(GL_SCISSOR_TEST); | 
 | 2095 |         glViewport(0, 0, hw_w, hw_h); | 
 | 2096 |         glMatrixMode(GL_PROJECTION); | 
 | 2097 |         glPopMatrix(); | 
 | 2098 |         glMatrixMode(GL_MODELVIEW); | 
 | 2099 |  | 
 | 2100 |  | 
 | 2101 |     } else { | 
 | 2102 |         result = BAD_VALUE; | 
 | 2103 |     } | 
 | 2104 |  | 
 | 2105 |     // release FBO resources | 
 | 2106 |     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | 
 | 2107 |     glDeleteRenderbuffersOES(1, &tname); | 
 | 2108 |     glDeleteFramebuffersOES(1, &name); | 
 | 2109 |     return result; | 
 | 2110 | } | 
 | 2111 |  | 
 | 2112 |  | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2113 | status_t SurfaceFlinger::captureScreen(DisplayID dpy, | 
 | 2114 |         sp<IMemoryHeap>* heap, | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2115 |         uint32_t* width, uint32_t* height, PixelFormat* format, | 
 | 2116 |         uint32_t sw, uint32_t sh) | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2117 | { | 
 | 2118 |     // only one display supported for now | 
 | 2119 |     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) | 
 | 2120 |         return BAD_VALUE; | 
 | 2121 |  | 
 | 2122 |     if (!GLExtensions::getInstance().haveFramebufferObject()) | 
 | 2123 |         return INVALID_OPERATION; | 
 | 2124 |  | 
 | 2125 |     class MessageCaptureScreen : public MessageBase { | 
 | 2126 |         SurfaceFlinger* flinger; | 
 | 2127 |         DisplayID dpy; | 
 | 2128 |         sp<IMemoryHeap>* heap; | 
 | 2129 |         uint32_t* w; | 
 | 2130 |         uint32_t* h; | 
 | 2131 |         PixelFormat* f; | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2132 |         uint32_t sw; | 
 | 2133 |         uint32_t sh; | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2134 |         status_t result; | 
 | 2135 |     public: | 
 | 2136 |         MessageCaptureScreen(SurfaceFlinger* flinger, DisplayID dpy, | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2137 |                 sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f, | 
 | 2138 |                 uint32_t sw, uint32_t sh) | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2139 |             : flinger(flinger), dpy(dpy), | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2140 |               heap(heap), w(w), h(h), f(f), sw(sw), sh(sh), result(PERMISSION_DENIED) | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2141 |         { | 
 | 2142 |         } | 
 | 2143 |         status_t getResult() const { | 
 | 2144 |             return result; | 
 | 2145 |         } | 
 | 2146 |         virtual bool handler() { | 
 | 2147 |             Mutex::Autolock _l(flinger->mStateLock); | 
 | 2148 |  | 
 | 2149 |             // if we have secure windows, never allow the screen capture | 
 | 2150 |             if (flinger->mSecureFrameBuffer) | 
 | 2151 |                 return true; | 
 | 2152 |  | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2153 |             result = flinger->captureScreenImplLocked(dpy, | 
 | 2154 |                     heap, w, h, f, sw, sh); | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2155 |  | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2156 |             return true; | 
 | 2157 |         } | 
 | 2158 |     }; | 
 | 2159 |  | 
 | 2160 |     sp<MessageBase> msg = new MessageCaptureScreen(this, | 
| Mathias Agopian | df85c45 | 2010-09-29 13:02:36 -0700 | [diff] [blame] | 2161 |             dpy, heap, width, height, format, sw, sh); | 
| Mathias Agopian | 1b0b30d | 2010-09-24 11:26:58 -0700 | [diff] [blame] | 2162 |     status_t res = postMessageSync(msg); | 
 | 2163 |     if (res == NO_ERROR) { | 
 | 2164 |         res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); | 
 | 2165 |     } | 
 | 2166 |     return res; | 
 | 2167 | } | 
 | 2168 |  | 
 | 2169 | // --------------------------------------------------------------------------- | 
 | 2170 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2171 | sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const | 
 | 2172 | { | 
 | 2173 |     sp<Layer> result; | 
 | 2174 |     Mutex::Autolock _l(mStateLock); | 
 | 2175 |     result = mLayerMap.valueFor( sur->asBinder() ).promote(); | 
 | 2176 |     return result; | 
 | 2177 | } | 
 | 2178 |  | 
 | 2179 | // --------------------------------------------------------------------------- | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2180 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2181 | Client::Client(const sp<SurfaceFlinger>& flinger) | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2182 |     : mFlinger(flinger), mNameGenerator(1) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2183 | { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2184 | } | 
 | 2185 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2186 | Client::~Client() | 
 | 2187 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2188 |     const size_t count = mLayers.size(); | 
 | 2189 |     for (size_t i=0 ; i<count ; i++) { | 
 | 2190 |         sp<LayerBaseClient> layer(mLayers.valueAt(i).promote()); | 
 | 2191 |         if (layer != 0) { | 
 | 2192 |             mFlinger->removeLayer(layer); | 
 | 2193 |         } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2194 |     } | 
 | 2195 | } | 
 | 2196 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2197 | status_t Client::initCheck() const { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2198 |     return NO_ERROR; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2199 | } | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 2200 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2201 | ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer) | 
 | 2202 | { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2203 |     int32_t name = android_atomic_inc(&mNameGenerator); | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2204 |     mLayers.add(name, layer); | 
 | 2205 |     return name; | 
 | 2206 | } | 
 | 2207 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2208 | void Client::detachLayer(const LayerBaseClient* layer) | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2209 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2210 |     // we do a linear search here, because this doesn't happen often | 
 | 2211 |     const size_t count = mLayers.size(); | 
 | 2212 |     for (size_t i=0 ; i<count ; i++) { | 
 | 2213 |         if (mLayers.valueAt(i) == layer) { | 
 | 2214 |             mLayers.removeItemsAt(i, 1); | 
 | 2215 |             break; | 
 | 2216 |         } | 
 | 2217 |     } | 
 | 2218 | } | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 2219 | sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { | 
 | 2220 |     sp<LayerBaseClient> lbc; | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2221 |     const wp<LayerBaseClient>& layer(mLayers.valueFor(i)); | 
 | 2222 |     if (layer != 0) { | 
 | 2223 |         lbc = layer.promote(); | 
 | 2224 |         LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i)); | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 2225 |     } | 
 | 2226 |     return lbc; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2227 | } | 
 | 2228 |  | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2229 | sp<IMemoryHeap> Client::getControlBlock() const { | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2230 |     return 0; | 
 | 2231 | } | 
 | 2232 | ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const { | 
 | 2233 |     return -1; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2234 | } | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2235 | sp<ISurface> Client::createSurface( | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2236 |         ISurfaceComposerClient::surface_data_t* params, int pid, | 
 | 2237 |         const String8& name, | 
 | 2238 |         DisplayID display, uint32_t w, uint32_t h, PixelFormat format, | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2239 |         uint32_t flags) | 
 | 2240 | { | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2241 |     return mFlinger->createSurface(this, pid, name, params, | 
 | 2242 |             display, w, h, format, flags); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2243 | } | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2244 | status_t Client::destroySurface(SurfaceID sid) { | 
 | 2245 |     return mFlinger->removeSurface(this, sid); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2246 | } | 
| Mathias Agopian | 96f0819 | 2010-06-02 23:28:45 -0700 | [diff] [blame] | 2247 | status_t Client::setState(int32_t count, const layer_state_t* states) { | 
 | 2248 |     return mFlinger->setClientState(this, count, states); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2249 | } | 
 | 2250 |  | 
 | 2251 | // --------------------------------------------------------------------------- | 
 | 2252 |  | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2253 | UserClient::UserClient(const sp<SurfaceFlinger>& flinger) | 
 | 2254 |     : ctrlblk(0), mBitmap(0), mFlinger(flinger) | 
 | 2255 | { | 
 | 2256 |     const int pgsize = getpagesize(); | 
 | 2257 |     const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1)); | 
 | 2258 |  | 
 | 2259 |     mCblkHeap = new MemoryHeapBase(cblksize, 0, | 
 | 2260 |             "SurfaceFlinger Client control-block"); | 
 | 2261 |  | 
 | 2262 |     ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase()); | 
 | 2263 |     if (ctrlblk) { // construct the shared structure in-place. | 
 | 2264 |         new(ctrlblk) SharedClient; | 
 | 2265 |     } | 
 | 2266 | } | 
 | 2267 |  | 
 | 2268 | UserClient::~UserClient() | 
 | 2269 | { | 
 | 2270 |     if (ctrlblk) { | 
 | 2271 |         ctrlblk->~SharedClient();  // destroy our shared-structure. | 
 | 2272 |     } | 
 | 2273 |  | 
 | 2274 |     /* | 
 | 2275 |      * When a UserClient dies, it's unclear what to do exactly. | 
 | 2276 |      * We could go ahead and destroy all surfaces linked to that client | 
 | 2277 |      * however, it wouldn't be fair to the main Client | 
 | 2278 |      * (usually the the window-manager), which might want to re-target | 
 | 2279 |      * the layer to another UserClient. | 
 | 2280 |      * I think the best is to do nothing, or not much; in most cases the | 
 | 2281 |      * WM itself will go ahead and clean things up when it detects a client of | 
 | 2282 |      * his has died. | 
 | 2283 |      * The remaining question is what to display? currently we keep | 
 | 2284 |      * just keep the current buffer. | 
 | 2285 |      */ | 
 | 2286 | } | 
 | 2287 |  | 
 | 2288 | status_t UserClient::initCheck() const { | 
 | 2289 |     return ctrlblk == 0 ? NO_INIT : NO_ERROR; | 
 | 2290 | } | 
 | 2291 |  | 
 | 2292 | void UserClient::detachLayer(const Layer* layer) | 
 | 2293 | { | 
 | 2294 |     int32_t name = layer->getToken(); | 
 | 2295 |     if (name >= 0) { | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 2296 |         int32_t mask = 1LU<<name; | 
 | 2297 |         if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) { | 
 | 2298 |             LOGW("token %d wasn't marked as used %08x", name, int(mBitmap)); | 
 | 2299 |         } | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2300 |     } | 
 | 2301 | } | 
 | 2302 |  | 
 | 2303 | sp<IMemoryHeap> UserClient::getControlBlock() const { | 
 | 2304 |     return mCblkHeap; | 
 | 2305 | } | 
 | 2306 |  | 
 | 2307 | ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const | 
 | 2308 | { | 
 | 2309 |     int32_t name = NAME_NOT_FOUND; | 
 | 2310 |     sp<Layer> layer(mFlinger->getLayer(sur)); | 
 | 2311 |     if (layer == 0) return name; | 
 | 2312 |  | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 2313 |     // if this layer already has a token, just return it | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2314 |     name = layer->getToken(); | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 2315 |     if ((name >= 0) && (layer->getClient() == this)) | 
 | 2316 |         return name; | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2317 |  | 
 | 2318 |     name = 0; | 
 | 2319 |     do { | 
 | 2320 |         int32_t mask = 1LU<<name; | 
 | 2321 |         if ((android_atomic_or(mask, &mBitmap) & mask) == 0) { | 
 | 2322 |             // we found and locked that name | 
| Mathias Agopian | 579b3f8 | 2010-06-08 19:54:15 -0700 | [diff] [blame] | 2323 |             status_t err = layer->setToken( | 
 | 2324 |                     const_cast<UserClient*>(this), ctrlblk, name); | 
 | 2325 |             if (err != NO_ERROR) { | 
 | 2326 |                 // free the name | 
 | 2327 |                 android_atomic_and(~mask, &mBitmap); | 
 | 2328 |                 name = err; | 
 | 2329 |             } | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2330 |             break; | 
 | 2331 |         } | 
 | 2332 |         if (++name > 31) | 
 | 2333 |             name = NO_MEMORY; | 
 | 2334 |     } while(name >= 0); | 
 | 2335 |  | 
| Mathias Agopian | 53503a9 | 2010-06-08 15:40:56 -0700 | [diff] [blame] | 2336 |     //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)", | 
 | 2337 |     //        sur->asBinder().get(), name, this, mBitmap); | 
| Mathias Agopian | b7e930d | 2010-06-01 15:12:58 -0700 | [diff] [blame] | 2338 |     return name; | 
 | 2339 | } | 
 | 2340 |  | 
 | 2341 | sp<ISurface> UserClient::createSurface( | 
 | 2342 |         ISurfaceComposerClient::surface_data_t* params, int pid, | 
 | 2343 |         const String8& name, | 
 | 2344 |         DisplayID display, uint32_t w, uint32_t h, PixelFormat format, | 
 | 2345 |         uint32_t flags) { | 
 | 2346 |     return 0; | 
 | 2347 | } | 
 | 2348 | status_t UserClient::destroySurface(SurfaceID sid) { | 
 | 2349 |     return INVALID_OPERATION; | 
 | 2350 | } | 
 | 2351 | status_t UserClient::setState(int32_t count, const layer_state_t* states) { | 
 | 2352 |     return INVALID_OPERATION; | 
 | 2353 | } | 
 | 2354 |  | 
 | 2355 | // --------------------------------------------------------------------------- | 
 | 2356 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2357 | GraphicPlane::GraphicPlane() | 
 | 2358 |     : mHw(0) | 
 | 2359 | { | 
 | 2360 | } | 
 | 2361 |  | 
 | 2362 | GraphicPlane::~GraphicPlane() { | 
 | 2363 |     delete mHw; | 
 | 2364 | } | 
 | 2365 |  | 
 | 2366 | bool GraphicPlane::initialized() const { | 
 | 2367 |     return mHw ? true : false; | 
 | 2368 | } | 
 | 2369 |  | 
| Mathias Agopian | 2b92d89 | 2010-02-08 15:49:35 -0800 | [diff] [blame] | 2370 | int GraphicPlane::getWidth() const { | 
 | 2371 |     return mWidth; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2372 | } | 
 | 2373 |  | 
| Mathias Agopian | 2b92d89 | 2010-02-08 15:49:35 -0800 | [diff] [blame] | 2374 | int GraphicPlane::getHeight() const { | 
 | 2375 |     return mHeight; | 
 | 2376 | } | 
 | 2377 |  | 
 | 2378 | void GraphicPlane::setDisplayHardware(DisplayHardware *hw) | 
 | 2379 | { | 
 | 2380 |     mHw = hw; | 
 | 2381 |  | 
 | 2382 |     // initialize the display orientation transform. | 
 | 2383 |     // it's a constant that should come from the display driver. | 
 | 2384 |     int displayOrientation = ISurfaceComposer::eOrientationDefault; | 
 | 2385 |     char property[PROPERTY_VALUE_MAX]; | 
 | 2386 |     if (property_get("ro.sf.hwrotation", property, NULL) > 0) { | 
 | 2387 |         //displayOrientation | 
 | 2388 |         switch (atoi(property)) { | 
 | 2389 |         case 90: | 
 | 2390 |             displayOrientation = ISurfaceComposer::eOrientation90; | 
 | 2391 |             break; | 
 | 2392 |         case 270: | 
 | 2393 |             displayOrientation = ISurfaceComposer::eOrientation270; | 
 | 2394 |             break; | 
 | 2395 |         } | 
 | 2396 |     } | 
 | 2397 |  | 
 | 2398 |     const float w = hw->getWidth(); | 
 | 2399 |     const float h = hw->getHeight(); | 
 | 2400 |     GraphicPlane::orientationToTransfrom(displayOrientation, w, h, | 
 | 2401 |             &mDisplayTransform); | 
 | 2402 |     if (displayOrientation & ISurfaceComposer::eOrientationSwapMask) { | 
 | 2403 |         mDisplayWidth = h; | 
 | 2404 |         mDisplayHeight = w; | 
 | 2405 |     } else { | 
 | 2406 |         mDisplayWidth = w; | 
 | 2407 |         mDisplayHeight = h; | 
 | 2408 |     } | 
 | 2409 |  | 
 | 2410 |     setOrientation(ISurfaceComposer::eOrientationDefault); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2411 | } | 
 | 2412 |  | 
 | 2413 | status_t GraphicPlane::orientationToTransfrom( | 
 | 2414 |         int orientation, int w, int h, Transform* tr) | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2415 | { | 
 | 2416 |     uint32_t flags = 0; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2417 |     switch (orientation) { | 
 | 2418 |     case ISurfaceComposer::eOrientationDefault: | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2419 |         flags = Transform::ROT_0; | 
 | 2420 |         break; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2421 |     case ISurfaceComposer::eOrientation90: | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2422 |         flags = Transform::ROT_90; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2423 |         break; | 
 | 2424 |     case ISurfaceComposer::eOrientation180: | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2425 |         flags = Transform::ROT_180; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2426 |         break; | 
 | 2427 |     case ISurfaceComposer::eOrientation270: | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2428 |         flags = Transform::ROT_270; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2429 |         break; | 
 | 2430 |     default: | 
 | 2431 |         return BAD_VALUE; | 
 | 2432 |     } | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2433 |     tr->set(flags, w, h); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2434 |     return NO_ERROR; | 
 | 2435 | } | 
 | 2436 |  | 
 | 2437 | status_t GraphicPlane::setOrientation(int orientation) | 
 | 2438 | { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2439 |     // If the rotation can be handled in hardware, this is where | 
 | 2440 |     // the magic should happen. | 
| Mathias Agopian | 2b92d89 | 2010-02-08 15:49:35 -0800 | [diff] [blame] | 2441 |  | 
 | 2442 |     const DisplayHardware& hw(displayHardware()); | 
 | 2443 |     const float w = mDisplayWidth; | 
 | 2444 |     const float h = mDisplayHeight; | 
 | 2445 |     mWidth = int(w); | 
 | 2446 |     mHeight = int(h); | 
 | 2447 |  | 
 | 2448 |     Transform orientationTransform; | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2449 |     GraphicPlane::orientationToTransfrom(orientation, w, h, | 
 | 2450 |             &orientationTransform); | 
 | 2451 |     if (orientation & ISurfaceComposer::eOrientationSwapMask) { | 
 | 2452 |         mWidth = int(h); | 
 | 2453 |         mHeight = int(w); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2454 |     } | 
| Mathias Agopian | eda6540 | 2010-02-22 03:15:57 -0800 | [diff] [blame] | 2455 |  | 
| Mathias Agopian | 0d1318b | 2009-03-27 17:58:20 -0700 | [diff] [blame] | 2456 |     mOrientation = orientation; | 
| Mathias Agopian | 2b92d89 | 2010-02-08 15:49:35 -0800 | [diff] [blame] | 2457 |     mGlobalTransform = mDisplayTransform * orientationTransform; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2458 |     return NO_ERROR; | 
 | 2459 | } | 
 | 2460 |  | 
 | 2461 | const DisplayHardware& GraphicPlane::displayHardware() const { | 
 | 2462 |     return *mHw; | 
 | 2463 | } | 
 | 2464 |  | 
| Mathias Agopian | 59119e6 | 2010-10-11 12:37:43 -0700 | [diff] [blame] | 2465 | DisplayHardware& GraphicPlane::editDisplayHardware() { | 
 | 2466 |     return *mHw; | 
 | 2467 | } | 
 | 2468 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2469 | const Transform& GraphicPlane::transform() const { | 
 | 2470 |     return mGlobalTransform; | 
 | 2471 | } | 
 | 2472 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 2473 | EGLDisplay GraphicPlane::getEGLDisplay() const { | 
 | 2474 |     return mHw->getEGLDisplay(); | 
 | 2475 | } | 
 | 2476 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 2477 | // --------------------------------------------------------------------------- | 
 | 2478 |  | 
 | 2479 | }; // namespace android |