2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <cutils/properties.h>
24 #include <utils/RefBase.h>
25 #include <utils/Log.h>
27 #include <ui/DisplayInfo.h>
28 #include <ui/PixelFormat.h>
30 #include <gui/Surface.h>
32 #include <hardware/gralloc.h>
34 #include "DisplayHardware/DisplaySurface.h"
35 #include "DisplayHardware/HWComposer.h"
36 #include "RenderEngine/RenderEngine.h"
39 #include "DisplayDevice.h"
40 #include "SurfaceFlinger.h"
43 // ----------------------------------------------------------------------------
44 using namespace android;
45 // ----------------------------------------------------------------------------
47 #ifdef EGL_ANDROID_swap_rectangle
48 static constexpr bool kEGLAndroidSwapRectangle = true;
50 static constexpr bool kEGLAndroidSwapRectangle = false;
53 #if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
54 // Dummy implementation in case it is missing.
55 inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
60 * Initialize the display to the specified values.
64 DisplayDevice::DisplayDevice(
65 const sp<SurfaceFlinger>& flinger,
70 const wp<IBinder>& displayToken,
71 const sp<DisplaySurface>& displaySurface,
72 const sp<IGraphicBufferProducer>& producer,
74 : lastCompositionHadVisibleLayers(false),
76 mType(type), mHwcDisplayId(hwcId),
77 mDisplayToken(displayToken),
78 mDisplaySurface(displaySurface),
79 mDisplay(EGL_NO_DISPLAY),
80 mSurface(EGL_NO_SURFACE),
81 mDisplayWidth(), mDisplayHeight(), mFormat(),
85 mSecureLayerVisible(false),
86 mLayerStack(NO_LAYER_STACK),
88 mPowerMode(HWC_POWER_MODE_OFF),
92 mNativeWindow = surface = new Surface(producer, false);
93 ANativeWindow* const window = mNativeWindow.get();
94 char property[PROPERTY_VALUE_MAX];
97 * Create our display's surface
100 EGLSurface eglSurface;
101 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
102 if (config == EGL_NO_CONFIG) {
103 config = RenderEngine::chooseEglConfig(display, format);
105 eglSurface = eglCreateWindowSurface(display, config, window, NULL);
106 eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth);
107 eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
109 // Make sure that composition can never be stalled by a virtual display
110 // consumer that isn't processing buffers fast enough. We have to do this
112 // * Here, in case the display is composed entirely by HWC.
113 // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
114 // window's swap interval in eglMakeCurrent, so they'll override the
115 // interval we set here.
116 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
117 window->setSwapInterval(window, 0);
121 mSurface = eglSurface;
124 mViewport.makeInvalid();
125 mFrame.makeInvalid();
127 // virtual displays are always considered enabled
128 mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
129 HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
131 // Name the display. The name will be replaced shortly if the display
132 // was created with createDisplay().
134 case DISPLAY_PRIMARY:
135 mDisplayName = "Built-in Screen";
137 case DISPLAY_EXTERNAL:
138 mDisplayName = "HDMI Screen";
141 mDisplayName = "Virtual Screen"; // e.g. Overlay #n
145 mPanelInverseMounted = false;
146 // Check if panel is inverse mounted (contents show up HV flipped)
147 property_get("persist.panel.inversemounted", property, "0");
148 mPanelInverseMounted = !!atoi(property);
150 // initialize the display orientation transform.
151 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
153 #ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
154 surface->allocateBuffers();
158 DisplayDevice::~DisplayDevice() {
159 if (mSurface != EGL_NO_SURFACE) {
160 eglDestroySurface(mDisplay, mSurface);
161 mSurface = EGL_NO_SURFACE;
165 void DisplayDevice::disconnect(HWComposer& hwc) {
166 if (mHwcDisplayId >= 0) {
167 hwc.disconnectDisplay(mHwcDisplayId);
168 if (mHwcDisplayId >= DISPLAY_VIRTUAL)
169 hwc.freeDisplayId(mHwcDisplayId);
174 bool DisplayDevice::isValid() const {
175 return mFlinger != NULL;
178 int DisplayDevice::getWidth() const {
179 return mDisplayWidth;
182 int DisplayDevice::getHeight() const {
183 return mDisplayHeight;
186 PixelFormat DisplayDevice::getFormat() const {
190 EGLSurface DisplayDevice::getEGLSurface() const {
194 void DisplayDevice::setDisplayName(const String8& displayName) {
195 if (!displayName.isEmpty()) {
196 // never override the name with an empty name
197 mDisplayName = displayName;
201 uint32_t DisplayDevice::getPageFlipCount() const {
202 return mPageFlipCount;
205 status_t DisplayDevice::compositionComplete() const {
206 return mDisplaySurface->compositionComplete();
209 void DisplayDevice::flip(const Region& dirty) const
211 mFlinger->getRenderEngine().checkErrors();
213 if (kEGLAndroidSwapRectangle) {
214 if (mFlags & SWAP_RECTANGLE) {
215 const Region newDirty(dirty.intersect(bounds()));
216 const Rect b(newDirty.getBounds());
217 eglSetSwapRectangleANDROID(mDisplay, mSurface,
218 b.left, b.top, b.width(), b.height());
225 status_t DisplayDevice::beginFrame(bool mustRecompose) const {
226 return mDisplaySurface->beginFrame(mustRecompose);
229 status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
230 DisplaySurface::CompositionType compositionType;
231 bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
232 bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
233 if (haveGles && haveHwc) {
234 compositionType = DisplaySurface::COMPOSITION_MIXED;
235 } else if (haveGles) {
236 compositionType = DisplaySurface::COMPOSITION_GLES;
237 } else if (haveHwc) {
238 compositionType = DisplaySurface::COMPOSITION_HWC;
240 // Nothing to do -- when turning the screen off we get a frame like
241 // this. Call it a HWC frame since we won't be doing any GLES work but
242 // will do a prepare/set cycle.
243 compositionType = DisplaySurface::COMPOSITION_HWC;
245 return mDisplaySurface->prepareFrame(compositionType);
248 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
249 // We need to call eglSwapBuffers() if:
250 // (1) we don't have a hardware composer, or
251 // (2) we did GLES composition this frame, and either
252 // (a) we have framebuffer target support (not present on legacy
253 // devices, where HWComposer::commit() handles things); or
254 // (b) this is a virtual display
255 if (hwc.initCheck() != NO_ERROR ||
256 (hwc.hasGlesComposition(mHwcDisplayId) &&
257 (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
258 EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
260 EGLint error = eglGetError();
261 if (error == EGL_CONTEXT_LOST ||
262 mType == DisplayDevice::DISPLAY_PRIMARY) {
263 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
264 mDisplay, mSurface, error);
266 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
267 mDisplay, mSurface, error);
272 status_t result = mDisplaySurface->advanceFrame();
273 if (result != NO_ERROR) {
274 ALOGE("[%s] failed pushing new frame to HWC: %d",
275 mDisplayName.string(), result);
279 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
280 if (hwc.initCheck() == NO_ERROR) {
281 mDisplaySurface->onFrameCommitted();
285 uint32_t DisplayDevice::getFlags() const
290 EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
291 EGLBoolean result = EGL_TRUE;
292 EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
293 if (sur != mSurface) {
294 result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
295 if (result == EGL_TRUE) {
296 if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
297 eglSwapInterval(dpy, 0);
300 setViewportAndProjection();
304 void DisplayDevice::setViewportAndProjection() const {
305 size_t w = mDisplayWidth;
306 size_t h = mDisplayHeight;
307 Rect sourceCrop(0, 0, w, h);
308 mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
309 false, Transform::ROT_0);
312 // ----------------------------------------------------------------------------
314 void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
315 mVisibleLayersSortedByZ = layers;
316 mSecureLayerVisible = false;
317 size_t count = layers.size();
318 for (size_t i=0 ; i<count ; i++) {
319 const sp<Layer>& layer(layers[i]);
320 if (layer->isSecure()) {
321 mSecureLayerVisible = true;
326 const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
327 return mVisibleLayersSortedByZ;
330 bool DisplayDevice::getSecureLayerVisible() const {
331 return mSecureLayerVisible;
334 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
336 if (repaintEverything) {
337 dirty.set(getBounds());
339 const Transform& planeTransform(mGlobalTransform);
340 dirty = planeTransform.transform(this->dirtyRegion);
341 dirty.andSelf(getBounds());
346 // ----------------------------------------------------------------------------
347 void DisplayDevice::setPowerMode(int mode) {
351 int DisplayDevice::getPowerMode() const {
355 bool DisplayDevice::isDisplayOn() const {
356 return (mPowerMode != HWC_POWER_MODE_OFF);
359 // ----------------------------------------------------------------------------
360 void DisplayDevice::setActiveConfig(int mode) {
361 mActiveConfig = mode;
364 int DisplayDevice::getActiveConfig() const {
365 return mActiveConfig;
368 // ----------------------------------------------------------------------------
370 void DisplayDevice::setLayerStack(uint32_t stack) {
372 dirtyRegion.set(bounds());
375 // ----------------------------------------------------------------------------
377 uint32_t DisplayDevice::getOrientationTransform() const {
378 uint32_t transform = 0;
379 switch (mOrientation) {
380 case DisplayState::eOrientationDefault:
381 transform = Transform::ROT_0;
383 case DisplayState::eOrientation90:
384 transform = Transform::ROT_90;
386 case DisplayState::eOrientation180:
387 transform = Transform::ROT_180;
389 case DisplayState::eOrientation270:
390 transform = Transform::ROT_270;
396 status_t DisplayDevice::orientationToTransfrom(
397 int orientation, int w, int h, Transform* tr)
400 char value[PROPERTY_VALUE_MAX];
401 property_get("ro.sf.hwrotation", value, "0");
402 int additionalRot = atoi(value);
406 if (orientation == DisplayState::eOrientationUnchanged) {
407 orientation = additionalRot;
409 orientation += additionalRot;
414 switch (orientation) {
415 case DisplayState::eOrientationDefault:
416 flags = Transform::ROT_0;
418 case DisplayState::eOrientation90:
419 flags = Transform::ROT_90;
421 case DisplayState::eOrientation180:
422 flags = Transform::ROT_180;
424 case DisplayState::eOrientation270:
425 flags = Transform::ROT_270;
431 if (DISPLAY_PRIMARY == mHwcDisplayId && isPanelInverseMounted()) {
432 flags = flags ^ Transform::ROT_180;
435 tr->set(flags, w, h);
439 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
440 dirtyRegion.set(getBounds());
442 if (mSurface != EGL_NO_SURFACE) {
443 eglDestroySurface(mDisplay, mSurface);
444 mSurface = EGL_NO_SURFACE;
447 mDisplaySurface->resizeBuffers(newWidth, newHeight);
449 ANativeWindow* const window = mNativeWindow.get();
450 mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
451 eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mDisplayWidth);
452 eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
454 LOG_FATAL_IF(mDisplayWidth != newWidth,
455 "Unable to set new width to %d", newWidth);
456 LOG_FATAL_IF(mDisplayHeight != newHeight,
457 "Unable to set new height to %d", newHeight);
460 void DisplayDevice::setProjection(int orientation,
461 const Rect& newViewport, const Rect& newFrame) {
462 Rect viewport(newViewport);
463 Rect frame(newFrame);
465 const int w = mDisplayWidth;
466 const int h = mDisplayHeight;
469 DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
471 if (!frame.isValid()) {
472 // the destination frame can be invalid if it has never been set,
473 // in that case we assume the whole display frame.
474 char value[PROPERTY_VALUE_MAX];
475 property_get("ro.sf.hwrotation", value, "0");
476 int additionalRot = atoi(value);
478 if (additionalRot == 90 || additionalRot == 270) {
485 if (viewport.isEmpty()) {
486 // viewport can be invalid if it has never been set, in that case
487 // we assume the whole display size.
488 // it's also invalid to have an empty viewport, so we handle that
489 // case in the same way.
490 viewport = Rect(w, h);
491 if (R.getOrientation() & Transform::ROT_90) {
492 // viewport is always specified in the logical orientation
493 // of the display (ie: post-rotation).
494 swap(viewport.right, viewport.bottom);
498 dirtyRegion.set(getBounds());
501 float src_width = viewport.width();
502 float src_height = viewport.height();
503 float dst_width = frame.width();
504 float dst_height = frame.height();
505 if (src_width != dst_width || src_height != dst_height) {
506 float sx = dst_width / src_width;
507 float sy = dst_height / src_height;
511 float src_x = viewport.left;
512 float src_y = viewport.top;
513 float dst_x = frame.left;
514 float dst_y = frame.top;
515 TL.set(-src_x, -src_y);
516 TP.set(dst_x, dst_y);
518 // The viewport and frame are both in the logical orientation.
519 // Apply the logical translation, scale to physical size, apply the
520 // physical translation and finally rotate to the physical orientation.
521 mGlobalTransform = R * TP * S * TL;
523 const uint8_t type = mGlobalTransform.getType();
524 mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
525 (type >= Transform::SCALE));
527 mScissor = mGlobalTransform.transform(viewport);
528 if (mScissor.isEmpty()) {
529 mScissor = getBounds();
532 mOrientation = orientation;
533 mViewport = viewport;
537 void DisplayDevice::dump(String8& result) const {
538 const Transform& tr(mGlobalTransform);
540 "+ DisplayDevice: %s\n"
541 " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
542 "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
543 " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
544 "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
545 mDisplayName.string(), mType, mHwcDisplayId,
546 mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
547 mOrientation, tr.getType(), getPageFlipCount(),
548 mIsSecure, mSecureLayerVisible, mPowerMode, mActiveConfig,
549 mVisibleLayersSortedByZ.size(),
550 mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
551 mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
552 mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
553 tr[0][0], tr[1][0], tr[2][0],
554 tr[0][1], tr[1][1], tr[2][1],
555 tr[0][2], tr[1][2], tr[2][2]);
558 mDisplaySurface->dumpAsString(surfaceDump);
559 result.append(surfaceDump);