DisplayDevice.cpp revision f460f55c84b0a75de749b8a784059f5ff423ed93
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 <gui/Surface.h> 31 32#include <hardware/gralloc.h> 33 34#include "DisplayHardware/DisplaySurface.h" 35#include "DisplayHardware/HWComposer.h" 36#include "RenderEngine/RenderEngine.h" 37 38#include "clz.h" 39#include "DisplayDevice.h" 40#include "SurfaceFlinger.h" 41#include "Layer.h" 42 43// ---------------------------------------------------------------------------- 44using namespace android; 45// ---------------------------------------------------------------------------- 46 47/* 48 * Initialize the display to the specified values. 49 * 50 */ 51 52DisplayDevice::DisplayDevice( 53 const sp<SurfaceFlinger>& flinger, 54 DisplayType type, 55 int32_t hwcId, 56 bool isSecure, 57 const wp<IBinder>& displayToken, 58 const sp<DisplaySurface>& displaySurface, 59 EGLConfig config) 60 : mFlinger(flinger), 61 mType(type), mHwcDisplayId(hwcId), 62 mDisplayToken(displayToken), 63 mDisplaySurface(displaySurface), 64 mDisplay(EGL_NO_DISPLAY), 65 mSurface(EGL_NO_SURFACE), 66 mDisplayWidth(), mDisplayHeight(), mFormat(), 67 mFlags(), 68 mPageFlipCount(), 69 mIsSecure(isSecure), 70 mSecureLayerVisible(false), 71 mScreenAcquired(false), 72 mLayerStack(NO_LAYER_STACK), 73 mOrientation() 74{ 75 mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer()); 76 ANativeWindow* const window = mNativeWindow.get(); 77 78 int format; 79 window->query(window, NATIVE_WINDOW_FORMAT, &format); 80 81 // Make sure that composition can never be stalled by a virtual display 82 // consumer that isn't processing buffers fast enough. We have to do this 83 // in two places: 84 // * Here, in case the display is composed entirely by HWC. 85 // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the 86 // window's swap interval in eglMakeCurrent, so they'll override the 87 // interval we set here. 88 if (mType >= DisplayDevice::DISPLAY_VIRTUAL) 89 window->setSwapInterval(window, 0); 90 91 /* 92 * Create our display's surface 93 */ 94 95 EGLSurface surface; 96 EGLint w, h; 97 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 98 surface = eglCreateWindowSurface(display, config, window, NULL); 99 eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth); 100 eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); 101 102 mDisplay = display; 103 mSurface = surface; 104 mFormat = format; 105 mPageFlipCount = 0; 106 mViewport.makeInvalid(); 107 mFrame.makeInvalid(); 108 109 // virtual displays are always considered enabled 110 mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL); 111 112 // Name the display. The name will be replaced shortly if the display 113 // was created with createDisplay(). 114 switch (mType) { 115 case DISPLAY_PRIMARY: 116 mDisplayName = "Built-in Screen"; 117 break; 118 case DISPLAY_EXTERNAL: 119 mDisplayName = "HDMI Screen"; 120 break; 121 default: 122 mDisplayName = "Virtual Screen"; // e.g. Overlay #n 123 break; 124 } 125 126 // initialize the display orientation transform. 127 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); 128} 129 130DisplayDevice::~DisplayDevice() { 131 if (mSurface != EGL_NO_SURFACE) { 132 eglDestroySurface(mDisplay, mSurface); 133 mSurface = EGL_NO_SURFACE; 134 } 135} 136 137void DisplayDevice::disconnect(HWComposer& hwc) { 138 if (mHwcDisplayId >= 0) { 139 hwc.disconnectDisplay(mHwcDisplayId); 140 if (mHwcDisplayId >= DISPLAY_VIRTUAL) 141 hwc.freeDisplayId(mHwcDisplayId); 142 mHwcDisplayId = -1; 143 } 144} 145 146bool DisplayDevice::isValid() const { 147 return mFlinger != NULL; 148} 149 150int DisplayDevice::getWidth() const { 151 return mDisplayWidth; 152} 153 154int DisplayDevice::getHeight() const { 155 return mDisplayHeight; 156} 157 158PixelFormat DisplayDevice::getFormat() const { 159 return mFormat; 160} 161 162EGLSurface DisplayDevice::getEGLSurface() const { 163 return mSurface; 164} 165 166void DisplayDevice::setDisplayName(const String8& displayName) { 167 if (!displayName.isEmpty()) { 168 // never override the name with an empty name 169 mDisplayName = displayName; 170 } 171} 172 173uint32_t DisplayDevice::getPageFlipCount() const { 174 return mPageFlipCount; 175} 176 177status_t DisplayDevice::compositionComplete() const { 178 return mDisplaySurface->compositionComplete(); 179} 180 181void DisplayDevice::flip(const Region& dirty) const 182{ 183 mFlinger->getRenderEngine().checkErrors(); 184 185 EGLDisplay dpy = mDisplay; 186 EGLSurface surface = mSurface; 187 188#ifdef EGL_ANDROID_swap_rectangle 189 if (mFlags & SWAP_RECTANGLE) { 190 const Region newDirty(dirty.intersect(bounds())); 191 const Rect b(newDirty.getBounds()); 192 eglSetSwapRectangleANDROID(dpy, surface, 193 b.left, b.top, b.width(), b.height()); 194 } 195#endif 196 197 mPageFlipCount++; 198} 199 200status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const { 201 DisplaySurface::CompositionType compositionType; 202 bool haveGles = hwc.hasGlesComposition(mHwcDisplayId); 203 bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId); 204 if (haveGles && haveHwc) { 205 compositionType = DisplaySurface::COMPOSITION_MIXED; 206 } else if (haveGles) { 207 compositionType = DisplaySurface::COMPOSITION_GLES; 208 } else if (haveHwc) { 209 compositionType = DisplaySurface::COMPOSITION_HWC; 210 } else { 211 // Nothing to do -- when turning the screen off we get a frame like 212 // this. Call it a HWC frame since we won't be doing any GLES work but 213 // will do a prepare/set cycle. 214 compositionType = DisplaySurface::COMPOSITION_HWC; 215 } 216 return mDisplaySurface->prepareFrame(compositionType); 217} 218 219void DisplayDevice::swapBuffers(HWComposer& hwc) const { 220 // We need to call eglSwapBuffers() unless: 221 // (a) there was no GLES composition this frame, or 222 // (b) we're using a legacy HWC with no framebuffer target support (in 223 // which case HWComposer::commit() handles things). 224 if (hwc.initCheck() != NO_ERROR || 225 (hwc.hasGlesComposition(mHwcDisplayId) && 226 hwc.supportsFramebufferTarget())) { 227 EGLBoolean success = eglSwapBuffers(mDisplay, mSurface); 228 if (!success) { 229 EGLint error = eglGetError(); 230 if (error == EGL_CONTEXT_LOST || 231 mType == DisplayDevice::DISPLAY_PRIMARY) { 232 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x", 233 mDisplay, mSurface, error); 234 } else { 235 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x", 236 mDisplay, mSurface, error); 237 } 238 } 239 } 240 241 status_t result = mDisplaySurface->advanceFrame(); 242 if (result != NO_ERROR) { 243 ALOGE("[%s] failed pushing new frame to HWC: %d", 244 mDisplayName.string(), result); 245 } 246} 247 248void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { 249 if (hwc.initCheck() == NO_ERROR) { 250 mDisplaySurface->onFrameCommitted(); 251 } 252} 253 254uint32_t DisplayDevice::getFlags() const 255{ 256 return mFlags; 257} 258 259EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const { 260 EGLBoolean result = EGL_TRUE; 261 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); 262 if (sur != mSurface) { 263 result = eglMakeCurrent(dpy, mSurface, mSurface, ctx); 264 if (result == EGL_TRUE) { 265 if (mType >= DisplayDevice::DISPLAY_VIRTUAL) 266 eglSwapInterval(dpy, 0); 267 setViewportAndProjection(); 268 } 269 } 270 return result; 271} 272 273void DisplayDevice::setViewportAndProjection() const { 274 size_t w = mDisplayWidth; 275 size_t h = mDisplayHeight; 276 mFlinger->getRenderEngine().setViewportAndProjection(w, h); 277} 278 279// ---------------------------------------------------------------------------- 280 281void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) { 282 mVisibleLayersSortedByZ = layers; 283 mSecureLayerVisible = false; 284 size_t count = layers.size(); 285 for (size_t i=0 ; i<count ; i++) { 286 const sp<Layer>& layer(layers[i]); 287 if (layer->isSecure()) { 288 mSecureLayerVisible = true; 289 } 290 } 291} 292 293const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const { 294 return mVisibleLayersSortedByZ; 295} 296 297bool DisplayDevice::getSecureLayerVisible() const { 298 return mSecureLayerVisible; 299} 300 301Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { 302 Region dirty; 303 if (repaintEverything) { 304 dirty.set(getBounds()); 305 } else { 306 const Transform& planeTransform(mGlobalTransform); 307 dirty = planeTransform.transform(this->dirtyRegion); 308 dirty.andSelf(getBounds()); 309 } 310 return dirty; 311} 312 313// ---------------------------------------------------------------------------- 314 315bool DisplayDevice::canDraw() const { 316 return mScreenAcquired; 317} 318 319void DisplayDevice::releaseScreen() const { 320 mScreenAcquired = false; 321} 322 323void DisplayDevice::acquireScreen() const { 324 mScreenAcquired = true; 325} 326 327bool DisplayDevice::isScreenAcquired() const { 328 return mScreenAcquired; 329} 330 331// ---------------------------------------------------------------------------- 332 333void DisplayDevice::setLayerStack(uint32_t stack) { 334 mLayerStack = stack; 335 dirtyRegion.set(bounds()); 336} 337 338// ---------------------------------------------------------------------------- 339 340status_t DisplayDevice::orientationToTransfrom( 341 int orientation, int w, int h, Transform* tr) 342{ 343 uint32_t flags = 0; 344 switch (orientation) { 345 case DisplayState::eOrientationDefault: 346 flags = Transform::ROT_0; 347 break; 348 case DisplayState::eOrientation90: 349 flags = Transform::ROT_90; 350 break; 351 case DisplayState::eOrientation180: 352 flags = Transform::ROT_180; 353 break; 354 case DisplayState::eOrientation270: 355 flags = Transform::ROT_270; 356 break; 357 default: 358 return BAD_VALUE; 359 } 360 tr->set(flags, w, h); 361 return NO_ERROR; 362} 363 364void DisplayDevice::setProjection(int orientation, 365 const Rect& newViewport, const Rect& newFrame) { 366 Rect viewport(newViewport); 367 Rect frame(newFrame); 368 369 const int w = mDisplayWidth; 370 const int h = mDisplayHeight; 371 372 Transform R; 373 DisplayDevice::orientationToTransfrom(orientation, w, h, &R); 374 375 if (!frame.isValid()) { 376 // the destination frame can be invalid if it has never been set, 377 // in that case we assume the whole display frame. 378 frame = Rect(w, h); 379 } 380 381 if (viewport.isEmpty()) { 382 // viewport can be invalid if it has never been set, in that case 383 // we assume the whole display size. 384 // it's also invalid to have an empty viewport, so we handle that 385 // case in the same way. 386 viewport = Rect(w, h); 387 if (R.getOrientation() & Transform::ROT_90) { 388 // viewport is always specified in the logical orientation 389 // of the display (ie: post-rotation). 390 swap(viewport.right, viewport.bottom); 391 } 392 } 393 394 dirtyRegion.set(getBounds()); 395 396 Transform TL, TP, S; 397 float src_width = viewport.width(); 398 float src_height = viewport.height(); 399 float dst_width = frame.width(); 400 float dst_height = frame.height(); 401 if (src_width != dst_width || src_height != dst_height) { 402 float sx = dst_width / src_width; 403 float sy = dst_height / src_height; 404 S.set(sx, 0, 0, sy); 405 } 406 407 float src_x = viewport.left; 408 float src_y = viewport.top; 409 float dst_x = frame.left; 410 float dst_y = frame.top; 411 TL.set(-src_x, -src_y); 412 TP.set(dst_x, dst_y); 413 414 // The viewport and frame are both in the logical orientation. 415 // Apply the logical translation, scale to physical size, apply the 416 // physical translation and finally rotate to the physical orientation. 417 mGlobalTransform = R * TP * S * TL; 418 419 const uint8_t type = mGlobalTransform.getType(); 420 mNeedsFiltering = (!mGlobalTransform.preserveRects() || 421 (type >= Transform::SCALE)); 422 423 mScissor = mGlobalTransform.transform(viewport); 424 if (mScissor.isEmpty()) { 425 mScissor = getBounds(); 426 } 427 428 mOrientation = orientation; 429 mViewport = viewport; 430 mFrame = frame; 431} 432 433void DisplayDevice::dump(String8& result) const { 434 const Transform& tr(mGlobalTransform); 435 result.appendFormat( 436 "+ DisplayDevice: %s\n" 437 " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " 438 "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n" 439 " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d]," 440 "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", 441 mDisplayName.string(), mType, mHwcDisplayId, 442 mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(), 443 mOrientation, tr.getType(), getPageFlipCount(), 444 mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(), 445 mViewport.left, mViewport.top, mViewport.right, mViewport.bottom, 446 mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, 447 mScissor.left, mScissor.top, mScissor.right, mScissor.bottom, 448 tr[0][0], tr[1][0], tr[2][0], 449 tr[0][1], tr[1][1], tr[2][1], 450 tr[0][2], tr[1][2], tr[2][2]); 451 452 String8 surfaceDump; 453 mDisplaySurface->dump(surfaceDump); 454 result.append(surfaceDump); 455} 456