DisplayDevice.cpp revision 4297734c1156fd8ede7e9c61b1e439f9e1c18cd9
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 17#include <stdlib.h> 18#include <stdio.h> 19#include <string.h> 20#include <math.h> 21 22#include <cutils/properties.h> 23 24#include <utils/RefBase.h> 25#include <utils/Log.h> 26 27#include <ui/DisplayInfo.h> 28#include <ui/PixelFormat.h> 29 30#include <GLES/gl.h> 31#include <EGL/egl.h> 32#include <EGL/eglext.h> 33 34#include <hardware/gralloc.h> 35 36#include "DisplayHardware/FramebufferSurface.h" 37#include "DisplayHardware/HWComposer.h" 38 39#include "DisplayDevice.h" 40#include "GLExtensions.h" 41#include "SurfaceFlinger.h" 42#include "LayerBase.h" 43 44// ---------------------------------------------------------------------------- 45using namespace android; 46// ---------------------------------------------------------------------------- 47 48static __attribute__((noinline)) 49void checkGLErrors() 50{ 51 do { 52 // there could be more than one error flag 53 GLenum error = glGetError(); 54 if (error == GL_NO_ERROR) 55 break; 56 ALOGE("GL error 0x%04x", int(error)); 57 } while(true); 58} 59 60static __attribute__((noinline)) 61void checkEGLErrors(const char* token) 62{ 63 struct EGLUtils { 64 static const char *strerror(EGLint err) { 65 switch (err){ 66 case EGL_SUCCESS: return "EGL_SUCCESS"; 67 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 68 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 69 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 70 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 71 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 72 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 73 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 74 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 75 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 76 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 77 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 78 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 79 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 80 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 81 default: return "UNKNOWN"; 82 } 83 } 84 }; 85 86 EGLint error = eglGetError(); 87 if (error && error != EGL_SUCCESS) { 88 ALOGE("%s: EGL error 0x%04x (%s)", 89 token, int(error), EGLUtils::strerror(error)); 90 } 91} 92 93// ---------------------------------------------------------------------------- 94 95/* 96 * Initialize the display to the specified values. 97 * 98 */ 99 100DisplayDevice::DisplayDevice( 101 const sp<SurfaceFlinger>& flinger, 102 int display, 103 const sp<ANativeWindow>& surface, 104 EGLConfig config) 105 : mFlinger(flinger), 106 mId(display), 107 mNativeWindow(surface), 108 mDisplay(EGL_NO_DISPLAY), 109 mSurface(EGL_NO_SURFACE), 110 mContext(EGL_NO_CONTEXT), 111 mDpiX(), mDpiY(), 112 mDensity(), 113 mDisplayWidth(), mDisplayHeight(), mFormat(), 114 mFlags(), 115 mPageFlipCount(), 116 mSecureLayerVisible(false), 117 mScreenAcquired(false), 118 mOrientation(), 119 mLayerStack(0) 120{ 121 init(config); 122} 123 124DisplayDevice::~DisplayDevice() { 125 if (mSurface != EGL_NO_SURFACE) { 126 eglDestroySurface(mDisplay, mSurface); 127 mSurface = EGL_NO_SURFACE; 128 } 129} 130 131bool DisplayDevice::isValid() const { 132 return mFlinger != NULL; 133} 134 135float DisplayDevice::getDpiX() const { 136 return mDpiX; 137} 138 139float DisplayDevice::getDpiY() const { 140 return mDpiY; 141} 142 143float DisplayDevice::getDensity() const { 144 return mDensity; 145} 146 147int DisplayDevice::getWidth() const { 148 return mDisplayWidth; 149} 150 151int DisplayDevice::getHeight() const { 152 return mDisplayHeight; 153} 154 155PixelFormat DisplayDevice::getFormat() const { 156 return mFormat; 157} 158 159EGLSurface DisplayDevice::getEGLSurface() const { 160 return mSurface; 161} 162 163void DisplayDevice::init(EGLConfig config) 164{ 165 ANativeWindow* const window = mNativeWindow.get(); 166 167 int concreteType; 168 window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType); 169 if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) { 170 mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get()); 171 } 172 173 int format; 174 window->query(window, NATIVE_WINDOW_FORMAT, &format); 175 mDpiX = window->xdpi; 176 mDpiY = window->ydpi; 177 178 // TODO: Not sure if display density should handled by SF any longer 179 class Density { 180 static int getDensityFromProperty(char const* propName) { 181 char property[PROPERTY_VALUE_MAX]; 182 int density = 0; 183 if (property_get(propName, property, NULL) > 0) { 184 density = atoi(property); 185 } 186 return density; 187 } 188 public: 189 static int getEmuDensity() { 190 return getDensityFromProperty("qemu.sf.lcd_density"); } 191 static int getBuildDensity() { 192 return getDensityFromProperty("ro.sf.lcd_density"); } 193 }; 194 // The density of the device is provided by a build property 195 mDensity = Density::getBuildDensity() / 160.0f; 196 if (mDensity == 0) { 197 // the build doesn't provide a density -- this is wrong! 198 // use xdpi instead 199 ALOGE("ro.sf.lcd_density must be defined as a build property"); 200 mDensity = mDpiX / 160.0f; 201 } 202 if (Density::getEmuDensity()) { 203 // if "qemu.sf.lcd_density" is specified, it overrides everything 204 mDpiX = mDpiY = mDensity = Density::getEmuDensity(); 205 mDensity /= 160.0f; 206 } 207 208 /* 209 * Create our display's surface 210 */ 211 212 EGLSurface surface; 213 EGLint w, h; 214 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 215 surface = eglCreateWindowSurface(display, config, window, NULL); 216 eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth); 217 eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); 218 219 if (mFramebufferSurface != NULL) { 220 if (mFramebufferSurface->isUpdateOnDemand()) { 221 mFlags |= PARTIAL_UPDATES; 222 // if we have partial updates, we definitely don't need to 223 // preserve the backbuffer, which may be costly. 224 eglSurfaceAttrib(display, surface, 225 EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); 226 } 227 } 228 229 mDisplay = display; 230 mSurface = surface; 231 mFormat = format; 232 mPageFlipCount = 0; 233 234 // initialize the display orientation transform. 235 DisplayDevice::setOrientation(ISurfaceComposer::eOrientationDefault); 236} 237 238uint32_t DisplayDevice::getPageFlipCount() const { 239 return mPageFlipCount; 240} 241 242status_t DisplayDevice::compositionComplete() const { 243 if (mFramebufferSurface == NULL) { 244 return NO_ERROR; 245 } 246 return mFramebufferSurface->compositionComplete(); 247} 248 249void DisplayDevice::flip(const Region& dirty) const 250{ 251 checkGLErrors(); 252 253 EGLDisplay dpy = mDisplay; 254 EGLSurface surface = mSurface; 255 256#ifdef EGL_ANDROID_swap_rectangle 257 if (mFlags & SWAP_RECTANGLE) { 258 const Region newDirty(dirty.intersect(bounds())); 259 const Rect b(newDirty.getBounds()); 260 eglSetSwapRectangleANDROID(dpy, surface, 261 b.left, b.top, b.width(), b.height()); 262 } 263#endif 264 265 if (mFlags & PARTIAL_UPDATES) { 266 if (mFramebufferSurface != NULL) { 267 mFramebufferSurface->setUpdateRectangle(dirty.getBounds()); 268 } 269 } 270 271 mPageFlipCount++; 272} 273 274uint32_t DisplayDevice::getFlags() const 275{ 276 return mFlags; 277} 278 279void DisplayDevice::dump(String8& res) const 280{ 281 if (mFramebufferSurface != NULL) { 282 mFramebufferSurface->dump(res); 283 } 284} 285 286void DisplayDevice::makeCurrent(const sp<const DisplayDevice>& hw, EGLContext ctx) { 287 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); 288 if (sur != hw->mSurface) { 289 EGLDisplay dpy = eglGetCurrentDisplay(); 290 eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx); 291 } 292} 293 294// ---------------------------------------------------------------------------- 295 296void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) { 297 mVisibleLayersSortedByZ = layers; 298 size_t count = layers.size(); 299 for (size_t i=0 ; i<count ; i++) { 300 if (layers[i]->isSecure()) { 301 mSecureLayerVisible = true; 302 } 303 } 304} 305 306Vector< sp<LayerBase> > DisplayDevice::getVisibleLayersSortedByZ() const { 307 return mVisibleLayersSortedByZ; 308} 309 310bool DisplayDevice::getSecureLayerVisible() const { 311 return mSecureLayerVisible; 312} 313 314// ---------------------------------------------------------------------------- 315 316bool DisplayDevice::canDraw() const { 317 return mScreenAcquired; 318} 319 320void DisplayDevice::releaseScreen() const { 321 mScreenAcquired = false; 322} 323 324void DisplayDevice::acquireScreen() const { 325 mScreenAcquired = true; 326} 327 328bool DisplayDevice::isScreenAcquired() const { 329 return mScreenAcquired; 330} 331 332// ---------------------------------------------------------------------------- 333 334status_t DisplayDevice::orientationToTransfrom( 335 int orientation, int w, int h, Transform* tr) 336{ 337 uint32_t flags = 0; 338 switch (orientation) { 339 case ISurfaceComposer::eOrientationDefault: 340 flags = Transform::ROT_0; 341 break; 342 case ISurfaceComposer::eOrientation90: 343 flags = Transform::ROT_90; 344 break; 345 case ISurfaceComposer::eOrientation180: 346 flags = Transform::ROT_180; 347 break; 348 case ISurfaceComposer::eOrientation270: 349 flags = Transform::ROT_270; 350 break; 351 default: 352 return BAD_VALUE; 353 } 354 tr->set(flags, w, h); 355 return NO_ERROR; 356} 357 358status_t DisplayDevice::setOrientation(int orientation) { 359 int w = mDisplayWidth; 360 int h = mDisplayHeight; 361 362 DisplayDevice::orientationToTransfrom( 363 orientation, w, h, &mGlobalTransform); 364 if (orientation & ISurfaceComposer::eOrientationSwapMask) { 365 int tmp = w; 366 w = h; 367 h = tmp; 368 } 369 mOrientation = orientation; 370 dirtyRegion.set(bounds()); 371 return NO_ERROR; 372} 373