| 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 <string.h> | 
 | 20 | #include <math.h> | 
 | 21 |  | 
 | 22 | #include <cutils/properties.h> | 
 | 23 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 24 | #include <utils/RefBase.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 25 | #include <utils/Log.h> | 
 | 26 |  | 
| Mathias Agopian | c666cae | 2012-07-25 18:56:13 -0700 | [diff] [blame] | 27 | #include <ui/DisplayInfo.h> | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 28 | #include <ui/PixelFormat.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 29 |  | 
| Mathias Agopian | e3c697f | 2013-02-14 17:11:02 -0800 | [diff] [blame] | 30 | #include <gui/Surface.h> | 
| Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 31 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 32 | #include <hardware/gralloc.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 33 |  | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 34 | #include "DisplayHardware/DisplaySurface.h" | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 35 | #include "DisplayHardware/HWComposer.h" | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 36 | #include "RenderEngine/RenderEngine.h" | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 37 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 38 | #include "clz.h" | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 39 | #include "DisplayDevice.h" | 
| Mathias Agopian | c7d14e2 | 2011-08-01 16:32:21 -0700 | [diff] [blame] | 40 | #include "SurfaceFlinger.h" | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 41 | #include "Layer.h" | 
| Mathias Agopian | 1f7bec6 | 2010-06-25 18:02:21 -0700 | [diff] [blame] | 42 |  | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 43 | // ---------------------------------------------------------------------------- | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 44 | using namespace android; | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 45 | // ---------------------------------------------------------------------------- | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 46 |  | 
| Andreas Gampe | 89fd4f7 | 2014-11-13 14:18:56 -0800 | [diff] [blame] | 47 | #ifdef EGL_ANDROID_swap_rectangle | 
 | 48 | static constexpr bool kEGLAndroidSwapRectangle = true; | 
 | 49 | #else | 
 | 50 | static constexpr bool kEGLAndroidSwapRectangle = false; | 
 | 51 | #endif | 
 | 52 |  | 
 | 53 | #if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle) | 
 | 54 | // Dummy implementation in case it is missing. | 
 | 55 | inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) { | 
 | 56 | } | 
 | 57 | #endif | 
 | 58 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 59 | /* | 
 | 60 |  * Initialize the display to the specified values. | 
 | 61 |  * | 
 | 62 |  */ | 
 | 63 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 64 | DisplayDevice::DisplayDevice( | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 65 |         const sp<SurfaceFlinger>& flinger, | 
| Jamie Gennis | dd3cb84 | 2012-10-19 18:19:11 -0700 | [diff] [blame] | 66 |         DisplayType type, | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 67 |         int32_t hwcId, | 
| Jesse Hall | 19e8729 | 2013-12-23 21:02:15 -0800 | [diff] [blame] | 68 |         int format, | 
| Jamie Gennis | dd3cb84 | 2012-10-19 18:19:11 -0700 | [diff] [blame] | 69 |         bool isSecure, | 
 | 70 |         const wp<IBinder>& displayToken, | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 71 |         const sp<DisplaySurface>& displaySurface, | 
| Mathias Agopian | db89edc | 2013-08-02 01:40:18 -0700 | [diff] [blame] | 72 |         const sp<IGraphicBufferProducer>& producer, | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 73 |         EGLConfig config) | 
| Jesse Hall | b7a0549 | 2014-08-14 15:45:06 -0700 | [diff] [blame] | 74 |     : lastCompositionHadVisibleLayers(false), | 
 | 75 |       mFlinger(flinger), | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 76 |       mType(type), mHwcDisplayId(hwcId), | 
| Chih-Wei Huang | 27e2562 | 2013-01-07 17:33:56 +0800 | [diff] [blame] | 77 |       mDisplayToken(displayToken), | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 78 |       mDisplaySurface(displaySurface), | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 79 |       mDisplay(EGL_NO_DISPLAY), | 
 | 80 |       mSurface(EGL_NO_SURFACE), | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 81 |       mDisplayWidth(), mDisplayHeight(), mFormat(), | 
 | 82 |       mFlags(), | 
 | 83 |       mPageFlipCount(), | 
| Jamie Gennis | dd3cb84 | 2012-10-19 18:19:11 -0700 | [diff] [blame] | 84 |       mIsSecure(isSecure), | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 85 |       mSecureLayerVisible(false), | 
| Jesse Hall | 01e2905 | 2013-02-19 16:13:35 -0800 | [diff] [blame] | 86 |       mLayerStack(NO_LAYER_STACK), | 
| Prashant Malani | 2c9b11f | 2014-05-25 01:36:31 -0700 | [diff] [blame] | 87 |       mOrientation(), | 
| Michael Lentine | 6c9e34a | 2014-07-14 13:48:55 -0700 | [diff] [blame] | 88 |       mPowerMode(HWC_POWER_MODE_OFF), | 
 | 89 |       mActiveConfig(0) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 90 | { | 
| Jesse Hall | 83cafff | 2013-09-16 15:24:53 -0700 | [diff] [blame] | 91 |     mNativeWindow = new Surface(producer, false); | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 92 |     ANativeWindow* const window = mNativeWindow.get(); | 
 | 93 |  | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 94 |     /* | 
 | 95 |      * Create our display's surface | 
 | 96 |      */ | 
 | 97 |  | 
 | 98 |     EGLSurface surface; | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 99 |     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | 
| Jesse Hall | 19e8729 | 2013-12-23 21:02:15 -0800 | [diff] [blame] | 100 |     if (config == EGL_NO_CONFIG) { | 
 | 101 |         config = RenderEngine::chooseEglConfig(display, format); | 
 | 102 |     } | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 103 |     surface = eglCreateWindowSurface(display, config, window, NULL); | 
 | 104 |     eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth); | 
 | 105 |     eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); | 
 | 106 |  | 
| John Dong | 4ee5696 | 2014-02-21 12:37:59 -0800 | [diff] [blame] | 107 |     // Make sure that composition can never be stalled by a virtual display | 
 | 108 |     // consumer that isn't processing buffers fast enough. We have to do this | 
 | 109 |     // in two places: | 
 | 110 |     // * Here, in case the display is composed entirely by HWC. | 
 | 111 |     // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the | 
 | 112 |     //   window's swap interval in eglMakeCurrent, so they'll override the | 
 | 113 |     //   interval we set here. | 
 | 114 |     if (mType >= DisplayDevice::DISPLAY_VIRTUAL) | 
 | 115 |         window->setSwapInterval(window, 0); | 
 | 116 |  | 
| Michael Lentine | 47e4540 | 2014-07-18 15:34:25 -0700 | [diff] [blame] | 117 |     mConfig = config; | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 118 |     mDisplay = display; | 
 | 119 |     mSurface = surface; | 
 | 120 |     mFormat  = format; | 
 | 121 |     mPageFlipCount = 0; | 
 | 122 |     mViewport.makeInvalid(); | 
 | 123 |     mFrame.makeInvalid(); | 
 | 124 |  | 
 | 125 |     // virtual displays are always considered enabled | 
| Prashant Malani | 2c9b11f | 2014-05-25 01:36:31 -0700 | [diff] [blame] | 126 |     mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ? | 
 | 127 |                   HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; | 
| Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 128 |  | 
 | 129 |     // Name the display.  The name will be replaced shortly if the display | 
 | 130 |     // was created with createDisplay(). | 
 | 131 |     switch (mType) { | 
 | 132 |         case DISPLAY_PRIMARY: | 
 | 133 |             mDisplayName = "Built-in Screen"; | 
 | 134 |             break; | 
 | 135 |         case DISPLAY_EXTERNAL: | 
 | 136 |             mDisplayName = "HDMI Screen"; | 
 | 137 |             break; | 
 | 138 |         default: | 
 | 139 |             mDisplayName = "Virtual Screen";    // e.g. Overlay #n | 
 | 140 |             break; | 
 | 141 |     } | 
 | 142 |  | 
 | 143 |     // initialize the display orientation transform. | 
 | 144 |     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 145 | } | 
 | 146 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 147 | DisplayDevice::~DisplayDevice() { | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 148 |     if (mSurface != EGL_NO_SURFACE) { | 
 | 149 |         eglDestroySurface(mDisplay, mSurface); | 
 | 150 |         mSurface = EGL_NO_SURFACE; | 
 | 151 |     } | 
 | 152 | } | 
 | 153 |  | 
| Jesse Hall | 02d8656 | 2013-03-25 14:43:23 -0700 | [diff] [blame] | 154 | void DisplayDevice::disconnect(HWComposer& hwc) { | 
 | 155 |     if (mHwcDisplayId >= 0) { | 
 | 156 |         hwc.disconnectDisplay(mHwcDisplayId); | 
 | 157 |         if (mHwcDisplayId >= DISPLAY_VIRTUAL) | 
 | 158 |             hwc.freeDisplayId(mHwcDisplayId); | 
 | 159 |         mHwcDisplayId = -1; | 
 | 160 |     } | 
 | 161 | } | 
 | 162 |  | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 163 | bool DisplayDevice::isValid() const { | 
 | 164 |     return mFlinger != NULL; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 165 | } | 
 | 166 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 167 | int DisplayDevice::getWidth() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 168 |     return mDisplayWidth; | 
 | 169 | } | 
 | 170 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 171 | int DisplayDevice::getHeight() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 172 |     return mDisplayHeight; | 
 | 173 | } | 
 | 174 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 175 | PixelFormat DisplayDevice::getFormat() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 176 |     return mFormat; | 
 | 177 | } | 
 | 178 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 179 | EGLSurface DisplayDevice::getEGLSurface() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 180 |     return mSurface; | 
 | 181 | } | 
 | 182 |  | 
| Mathias Agopian | 9e2463e | 2012-09-21 18:26:16 -0700 | [diff] [blame] | 183 | void DisplayDevice::setDisplayName(const String8& displayName) { | 
 | 184 |     if (!displayName.isEmpty()) { | 
 | 185 |         // never override the name with an empty name | 
 | 186 |         mDisplayName = displayName; | 
 | 187 |     } | 
 | 188 | } | 
 | 189 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 190 | uint32_t DisplayDevice::getPageFlipCount() const { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 191 |     return mPageFlipCount; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 192 | } | 
 | 193 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 194 | status_t DisplayDevice::compositionComplete() const { | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 195 |     return mDisplaySurface->compositionComplete(); | 
| Mathias Agopian | 74faca2 | 2009-09-17 16:18:16 -0700 | [diff] [blame] | 196 | } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 197 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 198 | void DisplayDevice::flip(const Region& dirty) const | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 199 | { | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 200 |     mFlinger->getRenderEngine().checkErrors(); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 201 |  | 
| Andreas Gampe | 89fd4f7 | 2014-11-13 14:18:56 -0800 | [diff] [blame] | 202 |     if (kEGLAndroidSwapRectangle) { | 
 | 203 |         if (mFlags & SWAP_RECTANGLE) { | 
 | 204 |             const Region newDirty(dirty.intersect(bounds())); | 
 | 205 |             const Rect b(newDirty.getBounds()); | 
 | 206 |             eglSetSwapRectangleANDROID(mDisplay, mSurface, | 
 | 207 |                     b.left, b.top, b.width(), b.height()); | 
 | 208 |         } | 
| Jesse Hall | 01e2905 | 2013-02-19 16:13:35 -0800 | [diff] [blame] | 209 |     } | 
| Mathias Agopian | d870703 | 2012-09-18 01:21:55 -0700 | [diff] [blame] | 210 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 211 |     mPageFlipCount++; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 212 | } | 
 | 213 |  | 
| Dan Stoza | 7143316 | 2014-02-04 16:22:36 -0800 | [diff] [blame] | 214 | status_t DisplayDevice::beginFrame(bool mustRecompose) const { | 
 | 215 |     return mDisplaySurface->beginFrame(mustRecompose); | 
| Jesse Hall | 028dc8f | 2013-08-20 16:35:32 -0700 | [diff] [blame] | 216 | } | 
 | 217 |  | 
| Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 218 | status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const { | 
 | 219 |     DisplaySurface::CompositionType compositionType; | 
 | 220 |     bool haveGles = hwc.hasGlesComposition(mHwcDisplayId); | 
 | 221 |     bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId); | 
 | 222 |     if (haveGles && haveHwc) { | 
 | 223 |         compositionType = DisplaySurface::COMPOSITION_MIXED; | 
 | 224 |     } else if (haveGles) { | 
 | 225 |         compositionType = DisplaySurface::COMPOSITION_GLES; | 
 | 226 |     } else if (haveHwc) { | 
 | 227 |         compositionType = DisplaySurface::COMPOSITION_HWC; | 
 | 228 |     } else { | 
 | 229 |         // Nothing to do -- when turning the screen off we get a frame like | 
 | 230 |         // this. Call it a HWC frame since we won't be doing any GLES work but | 
 | 231 |         // will do a prepare/set cycle. | 
 | 232 |         compositionType = DisplaySurface::COMPOSITION_HWC; | 
 | 233 |     } | 
 | 234 |     return mDisplaySurface->prepareFrame(compositionType); | 
 | 235 | } | 
 | 236 |  | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 237 | void DisplayDevice::swapBuffers(HWComposer& hwc) const { | 
| Andy McFadden | 22a99f0 | 2013-08-20 16:04:47 -0700 | [diff] [blame] | 238 |     // We need to call eglSwapBuffers() if: | 
 | 239 |     //  (1) we don't have a hardware composer, or | 
 | 240 |     //  (2) we did GLES composition this frame, and either | 
 | 241 |     //    (a) we have framebuffer target support (not present on legacy | 
 | 242 |     //        devices, where HWComposer::commit() handles things); or | 
 | 243 |     //    (b) this is a virtual display | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 244 |     if (hwc.initCheck() != NO_ERROR || | 
 | 245 |             (hwc.hasGlesComposition(mHwcDisplayId) && | 
| Andy McFadden | 22a99f0 | 2013-08-20 16:04:47 -0700 | [diff] [blame] | 246 |              (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) { | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 247 |         EGLBoolean success = eglSwapBuffers(mDisplay, mSurface); | 
 | 248 |         if (!success) { | 
 | 249 |             EGLint error = eglGetError(); | 
 | 250 |             if (error == EGL_CONTEXT_LOST || | 
 | 251 |                     mType == DisplayDevice::DISPLAY_PRIMARY) { | 
 | 252 |                 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x", | 
 | 253 |                         mDisplay, mSurface, error); | 
 | 254 |             } else { | 
 | 255 |                 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x", | 
 | 256 |                         mDisplay, mSurface, error); | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 257 |             } | 
 | 258 |         } | 
 | 259 |     } | 
| Mathias Agopian | 52e2148 | 2012-09-24 18:07:21 -0700 | [diff] [blame] | 260 |  | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 261 |     status_t result = mDisplaySurface->advanceFrame(); | 
 | 262 |     if (result != NO_ERROR) { | 
 | 263 |         ALOGE("[%s] failed pushing new frame to HWC: %d", | 
 | 264 |                 mDisplayName.string(), result); | 
| Mathias Agopian | 3234138 | 2012-09-25 19:16:28 -0700 | [diff] [blame] | 265 |     } | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 266 | } | 
 | 267 |  | 
 | 268 | void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { | 
 | 269 |     if (hwc.initCheck() == NO_ERROR) { | 
| Jesse Hall | 851cfe8 | 2013-03-20 13:44:00 -0700 | [diff] [blame] | 270 |         mDisplaySurface->onFrameCommitted(); | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 271 |     } | 
 | 272 | } | 
 | 273 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 274 | uint32_t DisplayDevice::getFlags() const | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 275 | { | 
 | 276 |     return mFlags; | 
 | 277 | } | 
 | 278 |  | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 279 | EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const { | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 280 |     EGLBoolean result = EGL_TRUE; | 
| Mathias Agopian | 52bbb1a | 2012-07-31 19:01:53 -0700 | [diff] [blame] | 281 |     EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 282 |     if (sur != mSurface) { | 
 | 283 |         result = eglMakeCurrent(dpy, mSurface, mSurface, ctx); | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 284 |         if (result == EGL_TRUE) { | 
| Jesse Hall | f460f55 | 2013-08-06 17:08:53 -0700 | [diff] [blame] | 285 |             if (mType >= DisplayDevice::DISPLAY_VIRTUAL) | 
 | 286 |                 eglSwapInterval(dpy, 0); | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 287 |         } | 
| Mathias Agopian | 52bbb1a | 2012-07-31 19:01:53 -0700 | [diff] [blame] | 288 |     } | 
| Mathias Agopian | 931bda1 | 2013-08-28 18:11:46 -0700 | [diff] [blame] | 289 |     setViewportAndProjection(); | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 290 |     return result; | 
| Mathias Agopian | 52bbb1a | 2012-07-31 19:01:53 -0700 | [diff] [blame] | 291 | } | 
 | 292 |  | 
| Mathias Agopian | 875d8e1 | 2013-06-07 15:35:48 -0700 | [diff] [blame] | 293 | void DisplayDevice::setViewportAndProjection() const { | 
 | 294 |     size_t w = mDisplayWidth; | 
 | 295 |     size_t h = mDisplayHeight; | 
| Dan Stoza | c187900 | 2014-05-22 15:59:05 -0700 | [diff] [blame] | 296 |     Rect sourceCrop(0, 0, w, h); | 
| Riley Andrews | c3ebe66 | 2014-09-04 16:20:31 -0700 | [diff] [blame] | 297 |     mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, | 
 | 298 |         false, Transform::ROT_0); | 
| Mathias Agopian | bae92d0 | 2012-09-28 01:00:47 -0700 | [diff] [blame] | 299 | } | 
 | 300 |  | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 301 | // ---------------------------------------------------------------------------- | 
 | 302 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 303 | void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 304 |     mVisibleLayersSortedByZ = layers; | 
| Mathias Agopian | ef7b9c7 | 2012-08-10 15:22:19 -0700 | [diff] [blame] | 305 |     mSecureLayerVisible = false; | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 306 |     size_t count = layers.size(); | 
 | 307 |     for (size_t i=0 ; i<count ; i++) { | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 308 |         const sp<Layer>& layer(layers[i]); | 
| Mathias Agopian | f5f714a | 2013-02-26 16:54:05 -0800 | [diff] [blame] | 309 |         if (layer->isSecure()) { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 310 |             mSecureLayerVisible = true; | 
 | 311 |         } | 
 | 312 |     } | 
 | 313 | } | 
 | 314 |  | 
| Mathias Agopian | 13127d8 | 2013-03-05 17:47:11 -0800 | [diff] [blame] | 315 | const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 316 |     return mVisibleLayersSortedByZ; | 
 | 317 | } | 
 | 318 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 319 | bool DisplayDevice::getSecureLayerVisible() const { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 320 |     return mSecureLayerVisible; | 
 | 321 | } | 
 | 322 |  | 
| Mathias Agopian | cd60f99 | 2012-08-16 16:28:27 -0700 | [diff] [blame] | 323 | Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { | 
 | 324 |     Region dirty; | 
| Mathias Agopian | cd60f99 | 2012-08-16 16:28:27 -0700 | [diff] [blame] | 325 |     if (repaintEverything) { | 
 | 326 |         dirty.set(getBounds()); | 
 | 327 |     } else { | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 328 |         const Transform& planeTransform(mGlobalTransform); | 
| Mathias Agopian | cd60f99 | 2012-08-16 16:28:27 -0700 | [diff] [blame] | 329 |         dirty = planeTransform.transform(this->dirtyRegion); | 
 | 330 |         dirty.andSelf(getBounds()); | 
 | 331 |     } | 
 | 332 |     return dirty; | 
 | 333 | } | 
 | 334 |  | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 335 | // ---------------------------------------------------------------------------- | 
| Prashant Malani | 2c9b11f | 2014-05-25 01:36:31 -0700 | [diff] [blame] | 336 | void DisplayDevice::setPowerMode(int mode) { | 
 | 337 |     mPowerMode = mode; | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 338 | } | 
 | 339 |  | 
| Prashant Malani | 2c9b11f | 2014-05-25 01:36:31 -0700 | [diff] [blame] | 340 | int DisplayDevice::getPowerMode()  const { | 
 | 341 |     return mPowerMode; | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 342 | } | 
 | 343 |  | 
| Prashant Malani | 2c9b11f | 2014-05-25 01:36:31 -0700 | [diff] [blame] | 344 | bool DisplayDevice::isDisplayOn() const { | 
 | 345 |     return (mPowerMode != HWC_POWER_MODE_OFF); | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 346 | } | 
 | 347 |  | 
 | 348 | // ---------------------------------------------------------------------------- | 
| Michael Lentine | 6c9e34a | 2014-07-14 13:48:55 -0700 | [diff] [blame] | 349 | void DisplayDevice::setActiveConfig(int mode) { | 
 | 350 |     mActiveConfig = mode; | 
 | 351 | } | 
 | 352 |  | 
 | 353 | int DisplayDevice::getActiveConfig()  const { | 
 | 354 |     return mActiveConfig; | 
 | 355 | } | 
 | 356 |  | 
 | 357 | // ---------------------------------------------------------------------------- | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 358 |  | 
| Mathias Agopian | 28947d7 | 2012-08-08 18:51:15 -0700 | [diff] [blame] | 359 | void DisplayDevice::setLayerStack(uint32_t stack) { | 
 | 360 |     mLayerStack = stack; | 
 | 361 |     dirtyRegion.set(bounds()); | 
 | 362 | } | 
 | 363 |  | 
 | 364 | // ---------------------------------------------------------------------------- | 
 | 365 |  | 
| Mathias Agopian | c1c05de | 2013-09-17 23:45:22 -0700 | [diff] [blame] | 366 | uint32_t DisplayDevice::getOrientationTransform() const { | 
 | 367 |     uint32_t transform = 0; | 
 | 368 |     switch (mOrientation) { | 
 | 369 |         case DisplayState::eOrientationDefault: | 
 | 370 |             transform = Transform::ROT_0; | 
 | 371 |             break; | 
 | 372 |         case DisplayState::eOrientation90: | 
 | 373 |             transform = Transform::ROT_90; | 
 | 374 |             break; | 
 | 375 |         case DisplayState::eOrientation180: | 
 | 376 |             transform = Transform::ROT_180; | 
 | 377 |             break; | 
 | 378 |         case DisplayState::eOrientation270: | 
 | 379 |             transform = Transform::ROT_270; | 
 | 380 |             break; | 
 | 381 |     } | 
 | 382 |     return transform; | 
 | 383 | } | 
 | 384 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 385 | status_t DisplayDevice::orientationToTransfrom( | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 386 |         int orientation, int w, int h, Transform* tr) | 
 | 387 | { | 
 | 388 |     uint32_t flags = 0; | 
 | 389 |     switch (orientation) { | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 390 |     case DisplayState::eOrientationDefault: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 391 |         flags = Transform::ROT_0; | 
 | 392 |         break; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 393 |     case DisplayState::eOrientation90: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 394 |         flags = Transform::ROT_90; | 
 | 395 |         break; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 396 |     case DisplayState::eOrientation180: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 397 |         flags = Transform::ROT_180; | 
 | 398 |         break; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 399 |     case DisplayState::eOrientation270: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 400 |         flags = Transform::ROT_270; | 
 | 401 |         break; | 
 | 402 |     default: | 
 | 403 |         return BAD_VALUE; | 
 | 404 |     } | 
 | 405 |     tr->set(flags, w, h); | 
 | 406 |     return NO_ERROR; | 
 | 407 | } | 
 | 408 |  | 
| Michael Lentine | 47e4540 | 2014-07-18 15:34:25 -0700 | [diff] [blame] | 409 | void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) { | 
 | 410 |     dirtyRegion.set(getBounds()); | 
 | 411 |  | 
| Michael Lentine | f2568de | 2014-08-20 10:51:23 -0700 | [diff] [blame] | 412 |     if (mSurface != EGL_NO_SURFACE) { | 
 | 413 |         eglDestroySurface(mDisplay, mSurface); | 
 | 414 |         mSurface = EGL_NO_SURFACE; | 
 | 415 |     } | 
 | 416 |  | 
| Michael Lentine | 47e4540 | 2014-07-18 15:34:25 -0700 | [diff] [blame] | 417 |     mDisplaySurface->resizeBuffers(newWidth, newHeight); | 
 | 418 |  | 
 | 419 |     ANativeWindow* const window = mNativeWindow.get(); | 
 | 420 |     mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL); | 
 | 421 |     eglQuerySurface(mDisplay, mSurface, EGL_WIDTH,  &mDisplayWidth); | 
 | 422 |     eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight); | 
 | 423 |  | 
 | 424 |     LOG_FATAL_IF(mDisplayWidth != newWidth, | 
 | 425 |                 "Unable to set new width to %d", newWidth); | 
 | 426 |     LOG_FATAL_IF(mDisplayHeight != newHeight, | 
 | 427 |                 "Unable to set new height to %d", newHeight); | 
 | 428 | } | 
 | 429 |  | 
| Mathias Agopian | 00e8c7a | 2012-09-04 19:30:46 -0700 | [diff] [blame] | 430 | void DisplayDevice::setProjection(int orientation, | 
| Mathias Agopian | f5f714a | 2013-02-26 16:54:05 -0800 | [diff] [blame] | 431 |         const Rect& newViewport, const Rect& newFrame) { | 
 | 432 |     Rect viewport(newViewport); | 
 | 433 |     Rect frame(newFrame); | 
 | 434 |  | 
 | 435 |     const int w = mDisplayWidth; | 
 | 436 |     const int h = mDisplayHeight; | 
 | 437 |  | 
 | 438 |     Transform R; | 
 | 439 |     DisplayDevice::orientationToTransfrom(orientation, w, h, &R); | 
 | 440 |  | 
 | 441 |     if (!frame.isValid()) { | 
 | 442 |         // the destination frame can be invalid if it has never been set, | 
 | 443 |         // in that case we assume the whole display frame. | 
 | 444 |         frame = Rect(w, h); | 
 | 445 |     } | 
 | 446 |  | 
 | 447 |     if (viewport.isEmpty()) { | 
 | 448 |         // viewport can be invalid if it has never been set, in that case | 
 | 449 |         // we assume the whole display size. | 
 | 450 |         // it's also invalid to have an empty viewport, so we handle that | 
 | 451 |         // case in the same way. | 
 | 452 |         viewport = Rect(w, h); | 
 | 453 |         if (R.getOrientation() & Transform::ROT_90) { | 
 | 454 |             // viewport is always specified in the logical orientation | 
 | 455 |             // of the display (ie: post-rotation). | 
 | 456 |             swap(viewport.right, viewport.bottom); | 
 | 457 |         } | 
 | 458 |     } | 
 | 459 |  | 
 | 460 |     dirtyRegion.set(getBounds()); | 
 | 461 |  | 
 | 462 |     Transform TL, TP, S; | 
 | 463 |     float src_width  = viewport.width(); | 
 | 464 |     float src_height = viewport.height(); | 
 | 465 |     float dst_width  = frame.width(); | 
 | 466 |     float dst_height = frame.height(); | 
 | 467 |     if (src_width != dst_width || src_height != dst_height) { | 
 | 468 |         float sx = dst_width  / src_width; | 
 | 469 |         float sy = dst_height / src_height; | 
 | 470 |         S.set(sx, 0, 0, sy); | 
 | 471 |     } | 
 | 472 |  | 
 | 473 |     float src_x = viewport.left; | 
 | 474 |     float src_y = viewport.top; | 
 | 475 |     float dst_x = frame.left; | 
 | 476 |     float dst_y = frame.top; | 
 | 477 |     TL.set(-src_x, -src_y); | 
 | 478 |     TP.set(dst_x, dst_y); | 
 | 479 |  | 
 | 480 |     // The viewport and frame are both in the logical orientation. | 
 | 481 |     // Apply the logical translation, scale to physical size, apply the | 
 | 482 |     // physical translation and finally rotate to the physical orientation. | 
 | 483 |     mGlobalTransform = R * TP * S * TL; | 
 | 484 |  | 
 | 485 |     const uint8_t type = mGlobalTransform.getType(); | 
 | 486 |     mNeedsFiltering = (!mGlobalTransform.preserveRects() || | 
 | 487 |             (type >= Transform::SCALE)); | 
 | 488 |  | 
 | 489 |     mScissor = mGlobalTransform.transform(viewport); | 
 | 490 |     if (mScissor.isEmpty()) { | 
| Mathias Agopian | 6c7f25a | 2013-05-09 20:37:10 -0700 | [diff] [blame] | 491 |         mScissor = getBounds(); | 
| Mathias Agopian | f5f714a | 2013-02-26 16:54:05 -0800 | [diff] [blame] | 492 |     } | 
 | 493 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 494 |     mOrientation = orientation; | 
| Mathias Agopian | 00e8c7a | 2012-09-04 19:30:46 -0700 | [diff] [blame] | 495 |     mViewport = viewport; | 
 | 496 |     mFrame = frame; | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 497 | } | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 498 |  | 
| Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 499 | void DisplayDevice::dump(String8& result) const { | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 500 |     const Transform& tr(mGlobalTransform); | 
| Mathias Agopian | 74d211a | 2013-04-22 16:55:35 +0200 | [diff] [blame] | 501 |     result.appendFormat( | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 502 |         "+ DisplayDevice: %s\n" | 
| Jesse Hall | 02d8656 | 2013-03-25 14:43:23 -0700 | [diff] [blame] | 503 |         "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " | 
| Michael Lentine | 6c9e34a | 2014-07-14 13:48:55 -0700 | [diff] [blame] | 504 |         "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n" | 
| Mathias Agopian | 766dc49 | 2012-10-30 18:08:06 -0700 | [diff] [blame] | 505 |         "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d]," | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 506 |         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", | 
| Jesse Hall | 02d8656 | 2013-03-25 14:43:23 -0700 | [diff] [blame] | 507 |         mDisplayName.string(), mType, mHwcDisplayId, | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 508 |         mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(), | 
 | 509 |         mOrientation, tr.getType(), getPageFlipCount(), | 
| Michael Lentine | 6c9e34a | 2014-07-14 13:48:55 -0700 | [diff] [blame] | 510 |         mIsSecure, mSecureLayerVisible, mPowerMode, mActiveConfig, | 
 | 511 |         mVisibleLayersSortedByZ.size(), | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 512 |         mViewport.left, mViewport.top, mViewport.right, mViewport.bottom, | 
 | 513 |         mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, | 
| Mathias Agopian | 766dc49 | 2012-10-30 18:08:06 -0700 | [diff] [blame] | 514 |         mScissor.left, mScissor.top, mScissor.right, mScissor.bottom, | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 515 |         tr[0][0], tr[1][0], tr[2][0], | 
 | 516 |         tr[0][1], tr[1][1], tr[2][1], | 
 | 517 |         tr[0][2], tr[1][2], tr[2][2]); | 
 | 518 |  | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 519 |     String8 surfaceDump; | 
| Dan Stoza | f10c46e | 2014-11-11 10:32:31 -0800 | [diff] [blame] | 520 |     mDisplaySurface->dumpAsString(surfaceDump); | 
| Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 521 |     result.append(surfaceDump); | 
| Mathias Agopian | 1d12d8a | 2012-09-18 01:38:00 -0700 | [diff] [blame] | 522 | } |