DisplayDevice.cpp revision 92a979a92c34b7de609ce2b1662c73bb8a2728b9
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 : mId(0), 102 mDisplay(EGL_NO_DISPLAY), 103 mSurface(EGL_NO_SURFACE), 104 mContext(EGL_NO_CONTEXT) 105{ 106} 107 108DisplayDevice::DisplayDevice( 109 const sp<SurfaceFlinger>& flinger, 110 int display, 111 const sp<SurfaceTextureClient>& surface, 112 EGLConfig config) 113 : mFlinger(flinger), 114 mId(display), 115 mNativeWindow(surface), 116 mDisplay(EGL_NO_DISPLAY), 117 mSurface(EGL_NO_SURFACE), 118 mContext(EGL_NO_CONTEXT), 119 mDpiX(), mDpiY(), 120 mRefreshRate(), 121 mDensity(), 122 mDisplayWidth(), mDisplayHeight(), mFormat(), 123 mFlags(), 124 mPageFlipCount(), 125 mRefreshPeriod(), 126 mSecureLayerVisible(false), 127 mScreenAcquired(false), 128 mOrientation(), 129 mLayerStack(0) 130{ 131 init(config); 132} 133 134DisplayDevice::~DisplayDevice() { 135 // DO NOT call terminate() from here, because we create 136 // temporaries of this class (on the stack typically), and we don't 137 // want to destroy the EGLSurface in that case 138} 139 140void DisplayDevice::terminate() { 141 if (mSurface != EGL_NO_SURFACE) { 142 eglDestroySurface(mDisplay, mSurface); 143 mSurface = EGL_NO_SURFACE; 144 } 145} 146 147bool DisplayDevice::isValid() const { 148 return mFlinger != NULL; 149} 150 151float DisplayDevice::getDpiX() const { 152 return mDpiX; 153} 154 155float DisplayDevice::getDpiY() const { 156 return mDpiY; 157} 158 159float DisplayDevice::getDensity() const { 160 return mDensity; 161} 162 163float DisplayDevice::getRefreshRate() const { 164 return mRefreshRate; 165} 166 167int DisplayDevice::getWidth() const { 168 return mDisplayWidth; 169} 170 171int DisplayDevice::getHeight() const { 172 return mDisplayHeight; 173} 174 175PixelFormat DisplayDevice::getFormat() const { 176 return mFormat; 177} 178 179EGLSurface DisplayDevice::getEGLSurface() const { 180 return mSurface; 181} 182 183status_t DisplayDevice::getInfo(DisplayInfo* info) const { 184 info->w = getWidth(); 185 info->h = getHeight(); 186 info->xdpi = getDpiX(); 187 info->ydpi = getDpiY(); 188 info->fps = getRefreshRate(); 189 info->density = getDensity(); 190 info->orientation = getOrientation(); 191 // TODO: this needs to go away (currently needed only by webkit) 192 getPixelFormatInfo(getFormat(), &info->pixelFormatInfo); 193 return NO_ERROR; 194} 195 196void DisplayDevice::init(EGLConfig config) 197{ 198 ANativeWindow* const window = mNativeWindow.get(); 199 200 int concreteType; 201 window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType); 202 if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) { 203 mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get()); 204 } 205 206 int format; 207 window->query(window, NATIVE_WINDOW_FORMAT, &format); 208 mDpiX = window->xdpi; 209 mDpiY = window->ydpi; 210 if (mFramebufferSurface != NULL) { 211 mRefreshRate = mFramebufferSurface->getRefreshRate(); 212 } else { 213 mRefreshRate = 60; 214 } 215 mRefreshPeriod = nsecs_t(1e9 / mRefreshRate); 216 217 218 // TODO: Not sure if display density should handled by SF any longer 219 class Density { 220 static int getDensityFromProperty(char const* propName) { 221 char property[PROPERTY_VALUE_MAX]; 222 int density = 0; 223 if (property_get(propName, property, NULL) > 0) { 224 density = atoi(property); 225 } 226 return density; 227 } 228 public: 229 static int getEmuDensity() { 230 return getDensityFromProperty("qemu.sf.lcd_density"); } 231 static int getBuildDensity() { 232 return getDensityFromProperty("ro.sf.lcd_density"); } 233 }; 234 // The density of the device is provided by a build property 235 mDensity = Density::getBuildDensity() / 160.0f; 236 if (mDensity == 0) { 237 // the build doesn't provide a density -- this is wrong! 238 // use xdpi instead 239 ALOGE("ro.sf.lcd_density must be defined as a build property"); 240 mDensity = mDpiX / 160.0f; 241 } 242 if (Density::getEmuDensity()) { 243 // if "qemu.sf.lcd_density" is specified, it overrides everything 244 mDpiX = mDpiY = mDensity = Density::getEmuDensity(); 245 mDensity /= 160.0f; 246 } 247 248 /* 249 * Create our display's surface 250 */ 251 252 EGLSurface surface; 253 EGLint w, h; 254 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 255 surface = eglCreateWindowSurface(display, config, window, NULL); 256 eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth); 257 eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); 258 259 if (mFramebufferSurface != NULL) { 260 if (mFramebufferSurface->isUpdateOnDemand()) { 261 mFlags |= PARTIAL_UPDATES; 262 // if we have partial updates, we definitely don't need to 263 // preserve the backbuffer, which may be costly. 264 eglSurfaceAttrib(display, surface, 265 EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); 266 } 267 } 268 269 mDisplay = display; 270 mSurface = surface; 271 mFormat = format; 272 mPageFlipCount = 0; 273 274 // initialize the display orientation transform. 275 DisplayDevice::setOrientation(ISurfaceComposer::eOrientationDefault); 276} 277 278uint32_t DisplayDevice::getPageFlipCount() const { 279 return mPageFlipCount; 280} 281 282nsecs_t DisplayDevice::getRefreshPeriod() const { 283 return mRefreshPeriod; 284} 285 286status_t DisplayDevice::compositionComplete() const { 287 if (mFramebufferSurface == NULL) { 288 return NO_ERROR; 289 } 290 return mFramebufferSurface->compositionComplete(); 291} 292 293void DisplayDevice::flip(const Region& dirty) const 294{ 295 checkGLErrors(); 296 297 EGLDisplay dpy = mDisplay; 298 EGLSurface surface = mSurface; 299 300#ifdef EGL_ANDROID_swap_rectangle 301 if (mFlags & SWAP_RECTANGLE) { 302 const Region newDirty(dirty.intersect(bounds())); 303 const Rect b(newDirty.getBounds()); 304 eglSetSwapRectangleANDROID(dpy, surface, 305 b.left, b.top, b.width(), b.height()); 306 } 307#endif 308 309 if (mFlags & PARTIAL_UPDATES) { 310 if (mFramebufferSurface != NULL) { 311 mFramebufferSurface->setUpdateRectangle(dirty.getBounds()); 312 } 313 } 314 315 mPageFlipCount++; 316} 317 318uint32_t DisplayDevice::getFlags() const 319{ 320 return mFlags; 321} 322 323void DisplayDevice::dump(String8& res) const 324{ 325 if (mFramebufferSurface != NULL) { 326 mFramebufferSurface->dump(res); 327 } 328} 329 330void DisplayDevice::makeCurrent(const DisplayDevice& hw, EGLContext ctx) { 331 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); 332 if (sur != hw.mSurface) { 333 EGLDisplay dpy = eglGetCurrentDisplay(); 334 eglMakeCurrent(dpy, hw.mSurface, hw.mSurface, ctx); 335 } 336} 337 338// ---------------------------------------------------------------------------- 339 340void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) { 341 mVisibleLayersSortedByZ = layers; 342 size_t count = layers.size(); 343 for (size_t i=0 ; i<count ; i++) { 344 if (layers[i]->isSecure()) { 345 mSecureLayerVisible = true; 346 } 347 } 348} 349 350Vector< sp<LayerBase> > DisplayDevice::getVisibleLayersSortedByZ() const { 351 return mVisibleLayersSortedByZ; 352} 353 354bool DisplayDevice::getSecureLayerVisible() const { 355 return mSecureLayerVisible; 356} 357 358// ---------------------------------------------------------------------------- 359 360bool DisplayDevice::canDraw() const { 361 return mScreenAcquired; 362} 363 364void DisplayDevice::releaseScreen() const { 365 mScreenAcquired = false; 366} 367 368void DisplayDevice::acquireScreen() const { 369 mScreenAcquired = true; 370} 371 372bool DisplayDevice::isScreenAcquired() const { 373 return mScreenAcquired; 374} 375 376// ---------------------------------------------------------------------------- 377 378status_t DisplayDevice::orientationToTransfrom( 379 int orientation, int w, int h, Transform* tr) 380{ 381 uint32_t flags = 0; 382 switch (orientation) { 383 case ISurfaceComposer::eOrientationDefault: 384 flags = Transform::ROT_0; 385 break; 386 case ISurfaceComposer::eOrientation90: 387 flags = Transform::ROT_90; 388 break; 389 case ISurfaceComposer::eOrientation180: 390 flags = Transform::ROT_180; 391 break; 392 case ISurfaceComposer::eOrientation270: 393 flags = Transform::ROT_270; 394 break; 395 default: 396 return BAD_VALUE; 397 } 398 tr->set(flags, w, h); 399 return NO_ERROR; 400} 401 402status_t DisplayDevice::setOrientation(int orientation) { 403 int w = mDisplayWidth; 404 int h = mDisplayHeight; 405 406 DisplayDevice::orientationToTransfrom( 407 orientation, w, h, &mGlobalTransform); 408 if (orientation & ISurfaceComposer::eOrientationSwapMask) { 409 int tmp = w; 410 w = h; 411 h = tmp; 412 } 413 mOrientation = orientation; 414 dirtyRegion.set(bounds()); 415 return NO_ERROR; 416} 417