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