| 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 |  | 
| Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 30 | #include <gui/SurfaceTextureClient.h> | 
 | 31 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 32 | #include <GLES/gl.h> | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 33 | #include <EGL/egl.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 34 | #include <EGL/eglext.h> | 
 | 35 |  | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 36 | #include <hardware/gralloc.h> | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 37 |  | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 38 | #include "DisplayHardware/FramebufferSurface.h" | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 39 | #include "DisplayHardware/HWComposer.h" | 
 | 40 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 41 | #include "clz.h" | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 42 | #include "DisplayDevice.h" | 
| Mathias Agopian | 1f7bec6 | 2010-06-25 18:02:21 -0700 | [diff] [blame] | 43 | #include "GLExtensions.h" | 
| Mathias Agopian | c7d14e2 | 2011-08-01 16:32:21 -0700 | [diff] [blame] | 44 | #include "SurfaceFlinger.h" | 
| Mathias Agopian | 921e6ac | 2012-07-23 23:11:29 -0700 | [diff] [blame] | 45 | #include "LayerBase.h" | 
| Mathias Agopian | 1f7bec6 | 2010-06-25 18:02:21 -0700 | [diff] [blame] | 46 |  | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 47 | // ---------------------------------------------------------------------------- | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 48 | using namespace android; | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 49 | // ---------------------------------------------------------------------------- | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 50 |  | 
 | 51 | static __attribute__((noinline)) | 
 | 52 | void checkGLErrors() | 
 | 53 | { | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 54 |     do { | 
 | 55 |         // there could be more than one error flag | 
 | 56 |         GLenum error = glGetError(); | 
 | 57 |         if (error == GL_NO_ERROR) | 
 | 58 |             break; | 
| Steve Block | e6f43dd | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 59 |         ALOGE("GL error 0x%04x", int(error)); | 
| Mathias Agopian | cbb288b | 2009-09-07 16:32:45 -0700 | [diff] [blame] | 60 |     } while(true); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 61 | } | 
 | 62 |  | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 63 | // ---------------------------------------------------------------------------- | 
 | 64 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 65 | /* | 
 | 66 |  * Initialize the display to the specified values. | 
 | 67 |  * | 
 | 68 |  */ | 
 | 69 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 70 | DisplayDevice::DisplayDevice( | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 71 |         const sp<SurfaceFlinger>& flinger, | 
| Mathias Agopian | 3ee454a | 2012-08-27 16:28:24 -0700 | [diff] [blame] | 72 |         DisplayType type, const wp<IBinder>& displayToken, | 
| Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 73 |         const sp<ANativeWindow>& nativeWindow, | 
 | 74 |         const sp<FramebufferSurface>& framebufferSurface, | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 75 |         EGLConfig config) | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 76 |     : mFlinger(flinger), | 
| Mathias Agopian | 3ee454a | 2012-08-27 16:28:24 -0700 | [diff] [blame] | 77 |       mType(type), mHwcDisplayId(-1), | 
| Jamie Gennis | 1a4d883 | 2012-08-02 20:11:05 -0700 | [diff] [blame] | 78 |       mNativeWindow(nativeWindow), | 
 | 79 |       mFramebufferSurface(framebufferSurface), | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 80 |       mDisplay(EGL_NO_DISPLAY), | 
 | 81 |       mSurface(EGL_NO_SURFACE), | 
 | 82 |       mContext(EGL_NO_CONTEXT), | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 83 |       mDisplayWidth(), mDisplayHeight(), mFormat(), | 
 | 84 |       mFlags(), | 
 | 85 |       mPageFlipCount(), | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 86 |       mSecureLayerVisible(false), | 
 | 87 |       mScreenAcquired(false), | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 88 |       mLayerStack(0), | 
 | 89 |       mOrientation() | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 90 | { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 91 |     init(config); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 92 | } | 
 | 93 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 94 | DisplayDevice::~DisplayDevice() { | 
| Mathias Agopian | 92a979a | 2012-08-02 18:32:23 -0700 | [diff] [blame] | 95 |     if (mSurface != EGL_NO_SURFACE) { | 
 | 96 |         eglDestroySurface(mDisplay, mSurface); | 
 | 97 |         mSurface = EGL_NO_SURFACE; | 
 | 98 |     } | 
 | 99 | } | 
 | 100 |  | 
 | 101 | bool DisplayDevice::isValid() const { | 
 | 102 |     return mFlinger != NULL; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 103 | } | 
 | 104 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 105 | int DisplayDevice::getWidth() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 106 |     return mDisplayWidth; | 
 | 107 | } | 
 | 108 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 109 | int DisplayDevice::getHeight() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 110 |     return mDisplayHeight; | 
 | 111 | } | 
 | 112 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 113 | PixelFormat DisplayDevice::getFormat() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 114 |     return mFormat; | 
 | 115 | } | 
 | 116 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 117 | EGLSurface DisplayDevice::getEGLSurface() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 118 |     return mSurface; | 
 | 119 | } | 
 | 120 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 121 | void DisplayDevice::init(EGLConfig config) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 122 | { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 123 |     ANativeWindow* const window = mNativeWindow.get(); | 
 | 124 |  | 
| Mathias Agopian | 6163091 | 2011-07-06 16:35:30 -0700 | [diff] [blame] | 125 |     int format; | 
| Mathias Agopian | 6163091 | 2011-07-06 16:35:30 -0700 | [diff] [blame] | 126 |     window->query(window, NATIVE_WINDOW_FORMAT, &format); | 
| Mathias Agopian | b5dd9c0 | 2012-03-22 12:15:54 -0700 | [diff] [blame] | 127 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 128 |     /* | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 129 |      * Create our display's surface | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 130 |      */ | 
 | 131 |  | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 132 |     EGLSurface surface; | 
 | 133 |     EGLint w, h; | 
 | 134 |     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | 
 | 135 |     surface = eglCreateWindowSurface(display, config, window, NULL); | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 136 |     eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth); | 
 | 137 |     eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 138 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 139 |     mDisplay = display; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 140 |     mSurface = surface; | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 141 |     mFormat  = format; | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 142 |     mPageFlipCount = 0; | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 143 |     mViewport.makeInvalid(); | 
 | 144 |     mFrame.makeInvalid(); | 
| Mathias Agopian | 1f7bec6 | 2010-06-25 18:02:21 -0700 | [diff] [blame] | 145 |  | 
| Mathias Agopian | 5f20e2d | 2012-08-10 18:50:38 -0700 | [diff] [blame] | 146 |     // external displays are always considered enabled | 
| Mathias Agopian | 3ee454a | 2012-08-27 16:28:24 -0700 | [diff] [blame] | 147 |     mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES); | 
 | 148 |  | 
 | 149 |     // get an h/w composer ID | 
 | 150 |     mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType); | 
| Mathias Agopian | 5f20e2d | 2012-08-10 18:50:38 -0700 | [diff] [blame] | 151 |  | 
| Mathias Agopian | 98a121a | 2012-07-24 21:08:59 -0700 | [diff] [blame] | 152 |     // initialize the display orientation transform. | 
| Mathias Agopian | 00e8c7a | 2012-09-04 19:30:46 -0700 | [diff] [blame] | 153 |     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 154 | } | 
 | 155 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 156 | uint32_t DisplayDevice::getPageFlipCount() const { | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 157 |     return mPageFlipCount; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 158 | } | 
 | 159 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 160 | status_t DisplayDevice::compositionComplete() const { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 161 |     if (mFramebufferSurface == NULL) { | 
 | 162 |         return NO_ERROR; | 
 | 163 |     } | 
 | 164 |     return mFramebufferSurface->compositionComplete(); | 
| Mathias Agopian | 74faca2 | 2009-09-17 16:18:16 -0700 | [diff] [blame] | 165 | } | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 166 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 167 | void DisplayDevice::flip(const Region& dirty) const | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 168 | { | 
 | 169 |     checkGLErrors(); | 
 | 170 |  | 
 | 171 |     EGLDisplay dpy = mDisplay; | 
 | 172 |     EGLSurface surface = mSurface; | 
 | 173 |  | 
| Mathias Agopian | 5e78e09 | 2009-06-11 17:19:54 -0700 | [diff] [blame] | 174 | #ifdef EGL_ANDROID_swap_rectangle     | 
| Mathias Agopian | df3ca30 | 2009-05-04 19:29:25 -0700 | [diff] [blame] | 175 |     if (mFlags & SWAP_RECTANGLE) { | 
| Mathias Agopian | b8a5560 | 2009-06-26 19:06:36 -0700 | [diff] [blame] | 176 |         const Region newDirty(dirty.intersect(bounds())); | 
 | 177 |         const Rect b(newDirty.getBounds()); | 
| Mathias Agopian | df3ca30 | 2009-05-04 19:29:25 -0700 | [diff] [blame] | 178 |         eglSetSwapRectangleANDROID(dpy, surface, | 
 | 179 |                 b.left, b.top, b.width(), b.height()); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 180 |     }  | 
| Mathias Agopian | 5e78e09 | 2009-06-11 17:19:54 -0700 | [diff] [blame] | 181 | #endif | 
 | 182 |      | 
| Mathias Agopian | 076b1cc | 2009-04-10 14:24:30 -0700 | [diff] [blame] | 183 |     mPageFlipCount++; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 184 | } | 
 | 185 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 186 | uint32_t DisplayDevice::getFlags() const | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 187 | { | 
 | 188 |     return mFlags; | 
 | 189 | } | 
 | 190 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 191 | void DisplayDevice::dump(String8& res) const | 
| Erik Gilling | 1d21a9c | 2010-12-01 16:38:01 -0800 | [diff] [blame] | 192 | { | 
| Mathias Agopian | a491260 | 2012-07-12 14:25:33 -0700 | [diff] [blame] | 193 |     if (mFramebufferSurface != NULL) { | 
 | 194 |         mFramebufferSurface->dump(res); | 
 | 195 |     } | 
| Erik Gilling | 1d21a9c | 2010-12-01 16:38:01 -0800 | [diff] [blame] | 196 | } | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 197 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 198 | EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, | 
 | 199 |         const sp<const DisplayDevice>& hw, EGLContext ctx) { | 
 | 200 |     EGLBoolean result = EGL_TRUE; | 
| Mathias Agopian | 52bbb1a | 2012-07-31 19:01:53 -0700 | [diff] [blame] | 201 |     EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); | 
| Mathias Agopian | 4297734 | 2012-08-05 00:40:46 -0700 | [diff] [blame] | 202 |     if (sur != hw->mSurface) { | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 203 |         result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx); | 
 | 204 |         if (result == EGL_TRUE) { | 
 | 205 |             GLsizei w = hw->mDisplayWidth; | 
 | 206 |             GLsizei h = hw->mDisplayHeight; | 
 | 207 |             glViewport(0, 0, w, h); | 
 | 208 |             glMatrixMode(GL_PROJECTION); | 
 | 209 |             glLoadIdentity(); | 
 | 210 |             // put the origin in the left-bottom corner | 
 | 211 |             glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h | 
 | 212 |         } | 
| Mathias Agopian | 52bbb1a | 2012-07-31 19:01:53 -0700 | [diff] [blame] | 213 |     } | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 214 |     return result; | 
| Mathias Agopian | 52bbb1a | 2012-07-31 19:01:53 -0700 | [diff] [blame] | 215 | } | 
 | 216 |  | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 217 | // ---------------------------------------------------------------------------- | 
 | 218 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 219 | void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 220 |     mVisibleLayersSortedByZ = layers; | 
| Mathias Agopian | ef7b9c7 | 2012-08-10 15:22:19 -0700 | [diff] [blame] | 221 |     mSecureLayerVisible = false; | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 222 |     size_t count = layers.size(); | 
 | 223 |     for (size_t i=0 ; i<count ; i++) { | 
 | 224 |         if (layers[i]->isSecure()) { | 
 | 225 |             mSecureLayerVisible = true; | 
 | 226 |         } | 
 | 227 |     } | 
 | 228 | } | 
 | 229 |  | 
| Mathias Agopian | 3ee454a | 2012-08-27 16:28:24 -0700 | [diff] [blame] | 230 | const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 231 |     return mVisibleLayersSortedByZ; | 
 | 232 | } | 
 | 233 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 234 | bool DisplayDevice::getSecureLayerVisible() const { | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 235 |     return mSecureLayerVisible; | 
 | 236 | } | 
 | 237 |  | 
| Mathias Agopian | cd60f99 | 2012-08-16 16:28:27 -0700 | [diff] [blame] | 238 | Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { | 
 | 239 |     Region dirty; | 
| Mathias Agopian | cd60f99 | 2012-08-16 16:28:27 -0700 | [diff] [blame] | 240 |     if (repaintEverything) { | 
 | 241 |         dirty.set(getBounds()); | 
 | 242 |     } else { | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 243 |         const Transform& planeTransform(mGlobalTransform); | 
| Mathias Agopian | cd60f99 | 2012-08-16 16:28:27 -0700 | [diff] [blame] | 244 |         dirty = planeTransform.transform(this->dirtyRegion); | 
 | 245 |         dirty.andSelf(getBounds()); | 
 | 246 |     } | 
 | 247 |     return dirty; | 
 | 248 | } | 
 | 249 |  | 
| Mathias Agopian | 3b1d2b6 | 2012-07-11 13:48:17 -0700 | [diff] [blame] | 250 | // ---------------------------------------------------------------------------- | 
 | 251 |  | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 252 | bool DisplayDevice::canDraw() const { | 
 | 253 |     return mScreenAcquired; | 
 | 254 | } | 
 | 255 |  | 
 | 256 | void DisplayDevice::releaseScreen() const { | 
 | 257 |     mScreenAcquired = false; | 
 | 258 | } | 
 | 259 |  | 
 | 260 | void DisplayDevice::acquireScreen() const { | 
 | 261 |     mScreenAcquired = true; | 
 | 262 | } | 
 | 263 |  | 
 | 264 | bool DisplayDevice::isScreenAcquired() const { | 
 | 265 |     return mScreenAcquired; | 
 | 266 | } | 
 | 267 |  | 
 | 268 | // ---------------------------------------------------------------------------- | 
 | 269 |  | 
| Mathias Agopian | 28947d7 | 2012-08-08 18:51:15 -0700 | [diff] [blame] | 270 | void DisplayDevice::setLayerStack(uint32_t stack) { | 
 | 271 |     mLayerStack = stack; | 
 | 272 |     dirtyRegion.set(bounds()); | 
 | 273 | } | 
 | 274 |  | 
 | 275 | // ---------------------------------------------------------------------------- | 
 | 276 |  | 
| Mathias Agopian | 0f2f5ff | 2012-07-31 23:09:07 -0700 | [diff] [blame] | 277 | status_t DisplayDevice::orientationToTransfrom( | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 278 |         int orientation, int w, int h, Transform* tr) | 
 | 279 | { | 
 | 280 |     uint32_t flags = 0; | 
 | 281 |     switch (orientation) { | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 282 |     case DisplayState::eOrientationDefault: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 283 |         flags = Transform::ROT_0; | 
 | 284 |         break; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 285 |     case DisplayState::eOrientation90: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 286 |         flags = Transform::ROT_90; | 
 | 287 |         break; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 288 |     case DisplayState::eOrientation180: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 289 |         flags = Transform::ROT_180; | 
 | 290 |         break; | 
| Mathias Agopian | 3165cc2 | 2012-08-08 19:42:09 -0700 | [diff] [blame] | 291 |     case DisplayState::eOrientation270: | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 292 |         flags = Transform::ROT_270; | 
 | 293 |         break; | 
 | 294 |     default: | 
 | 295 |         return BAD_VALUE; | 
 | 296 |     } | 
 | 297 |     tr->set(flags, w, h); | 
 | 298 |     return NO_ERROR; | 
 | 299 | } | 
 | 300 |  | 
| Mathias Agopian | 00e8c7a | 2012-09-04 19:30:46 -0700 | [diff] [blame] | 301 | void DisplayDevice::setProjection(int orientation, | 
 | 302 |         const Rect& viewport, const Rect& frame) { | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 303 |     mOrientation = orientation; | 
| Mathias Agopian | 00e8c7a | 2012-09-04 19:30:46 -0700 | [diff] [blame] | 304 |     mViewport = viewport; | 
 | 305 |     mFrame = frame; | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 306 |     updateGeometryTransform(); | 
 | 307 | } | 
 | 308 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 309 | void DisplayDevice::updateGeometryTransform() { | 
| Mathias Agopian | 98a121a | 2012-07-24 21:08:59 -0700 | [diff] [blame] | 310 |     int w = mDisplayWidth; | 
 | 311 |     int h = mDisplayHeight; | 
| Jesse Hall | 6360ec4 | 2012-09-12 13:49:10 -0700 | [diff] [blame^] | 312 |     Transform T, R, S; | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 313 |     if (DisplayDevice::orientationToTransfrom( | 
 | 314 |             mOrientation, w, h, &R) == NO_ERROR) { | 
 | 315 |         dirtyRegion.set(bounds()); | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 316 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 317 |         Rect viewport(mViewport); | 
 | 318 |         Rect frame(mFrame); | 
 | 319 |  | 
 | 320 |         if (!frame.isValid()) { | 
 | 321 |             // the destination frame can be invalid if it has never been set, | 
 | 322 |             // in that case we assume the whole display frame. | 
 | 323 |             frame = Rect(w, h); | 
 | 324 |         } | 
 | 325 |  | 
 | 326 |         if (viewport.isEmpty()) { | 
 | 327 |             // viewport can be invalid if it has never been set, in that case | 
 | 328 |             // we assume the whole display size. | 
 | 329 |             // it's also invalid to have an empty viewport, so we handle that | 
 | 330 |             // case in the same way. | 
 | 331 |             viewport = Rect(w, h); | 
 | 332 |             if (R.getOrientation() & Transform::ROT_90) { | 
 | 333 |                 // viewport is always specified in the logical orientation | 
 | 334 |                 // of the display (ie: post-rotation). | 
 | 335 |                 swap(viewport.right, viewport.bottom); | 
 | 336 |             } | 
 | 337 |         } | 
 | 338 |  | 
 | 339 |         float src_width  = viewport.width(); | 
 | 340 |         float src_height = viewport.height(); | 
 | 341 |         float dst_width  = frame.width(); | 
 | 342 |         float dst_height = frame.height(); | 
| Jesse Hall | 6360ec4 | 2012-09-12 13:49:10 -0700 | [diff] [blame^] | 343 |         if (src_width != dst_width || src_height != dst_height) { | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 344 |             float sx = dst_width  / src_width; | 
 | 345 |             float sy = dst_height / src_height; | 
 | 346 |             S.set(sx, 0, 0, sy); | 
 | 347 |         } | 
| Jesse Hall | 6360ec4 | 2012-09-12 13:49:10 -0700 | [diff] [blame^] | 348 |  | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 349 |         float src_x = viewport.left; | 
 | 350 |         float src_y = viewport.top; | 
 | 351 |         float dst_x = frame.left; | 
 | 352 |         float dst_y = frame.top; | 
 | 353 |         float tx = dst_x - src_x; | 
 | 354 |         float ty = dst_y - src_y; | 
| Jesse Hall | 6360ec4 | 2012-09-12 13:49:10 -0700 | [diff] [blame^] | 355 |         T.set(tx, ty); | 
| Mathias Agopian | da8d0a5 | 2012-09-04 15:05:38 -0700 | [diff] [blame] | 356 |  | 
| Jesse Hall | 6360ec4 | 2012-09-12 13:49:10 -0700 | [diff] [blame^] | 357 |         // The viewport and frame are both in the logical orientation, so the | 
 | 358 |         // translation is also in that space. So translation must be applied | 
 | 359 |         // before rotating from logical to physical orientation. | 
 | 360 |         mGlobalTransform = S * R * T; | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 361 |     } | 
| Mathias Agopian | 1b03149 | 2012-06-20 17:51:20 -0700 | [diff] [blame] | 362 | } |