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