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