123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- /*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <cutils/properties.h>
- #include <utils/RefBase.h>
- #include <utils/Log.h>
- #include <ui/DisplayInfo.h>
- #include <ui/PixelFormat.h>
- #include <gui/Surface.h>
- #include <hardware/gralloc.h>
- #include "DisplayHardware/DisplaySurface.h"
- #include "DisplayHardware/HWComposer.h"
- #include "RenderEngine/RenderEngine.h"
- #include "clz.h"
- #include "DisplayDevice.h"
- #include "SurfaceFlinger.h"
- #include "Layer.h"
- // ----------------------------------------------------------------------------
- using namespace android;
- // ----------------------------------------------------------------------------
- #ifdef EGL_ANDROID_swap_rectangle
- static constexpr bool kEGLAndroidSwapRectangle = true;
- #else
- static constexpr bool kEGLAndroidSwapRectangle = false;
- #endif
- #if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
- // Dummy implementation in case it is missing.
- inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
- }
- #endif
- /*
- * Initialize the display to the specified values.
- *
- */
- DisplayDevice::DisplayDevice(
- const sp<SurfaceFlinger>& flinger,
- DisplayType type,
- int32_t hwcId,
- int format,
- bool isSecure,
- const wp<IBinder>& displayToken,
- const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
- EGLConfig config)
- : lastCompositionHadVisibleLayers(false),
- mFlinger(flinger),
- mType(type), mHwcDisplayId(hwcId),
- mDisplayToken(displayToken),
- mDisplaySurface(displaySurface),
- mDisplay(EGL_NO_DISPLAY),
- mSurface(EGL_NO_SURFACE),
- mDisplayWidth(), mDisplayHeight(), mFormat(),
- mFlags(),
- mPageFlipCount(),
- mIsSecure(isSecure),
- mSecureLayerVisible(false),
- mLayerStack(NO_LAYER_STACK),
- mOrientation(),
- mPowerMode(HWC_POWER_MODE_OFF),
- mActiveConfig(0)
- {
- Surface* surface;
- mNativeWindow = surface = new Surface(producer, false);
- ANativeWindow* const window = mNativeWindow.get();
- char property[PROPERTY_VALUE_MAX];
- /*
- * Create our display's surface
- */
- EGLSurface eglSurface;
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (config == EGL_NO_CONFIG) {
- config = RenderEngine::chooseEglConfig(display, format);
- }
- eglSurface = eglCreateWindowSurface(display, config, window, NULL);
- eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth);
- eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
- // Make sure that composition can never be stalled by a virtual display
- // consumer that isn't processing buffers fast enough. We have to do this
- // in two places:
- // * Here, in case the display is composed entirely by HWC.
- // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
- // window's swap interval in eglMakeCurrent, so they'll override the
- // interval we set here.
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- window->setSwapInterval(window, 0);
- mConfig = config;
- mDisplay = display;
- mSurface = eglSurface;
- mFormat = format;
- mPageFlipCount = 0;
- mViewport.makeInvalid();
- mFrame.makeInvalid();
- // virtual displays are always considered enabled
- mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
- HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
- // Name the display. The name will be replaced shortly if the display
- // was created with createDisplay().
- switch (mType) {
- case DISPLAY_PRIMARY:
- mDisplayName = "Built-in Screen";
- break;
- case DISPLAY_EXTERNAL:
- mDisplayName = "HDMI Screen";
- break;
- default:
- mDisplayName = "Virtual Screen"; // e.g. Overlay #n
- break;
- }
- mPanelMountFlip = 0;
- // 1: H-Flip, 2: V-Flip, 3: 180 (HV Flip)
- property_get("persist.panel.mountflip", property, "0");
- mPanelMountFlip = atoi(property);
- // initialize the display orientation transform.
- setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
- #ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
- surface->allocateBuffers();
- #endif
- }
- DisplayDevice::~DisplayDevice() {
- if (mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mDisplay, mSurface);
- mSurface = EGL_NO_SURFACE;
- }
- }
- void DisplayDevice::disconnect(HWComposer& hwc) {
- if (mHwcDisplayId >= 0) {
- hwc.disconnectDisplay(mHwcDisplayId);
- if (mHwcDisplayId >= DISPLAY_VIRTUAL)
- hwc.freeDisplayId(mHwcDisplayId);
- mHwcDisplayId = -1;
- }
- }
- bool DisplayDevice::isValid() const {
- return mFlinger != NULL;
- }
- int DisplayDevice::getWidth() const {
- return mDisplayWidth;
- }
- int DisplayDevice::getHeight() const {
- return mDisplayHeight;
- }
- PixelFormat DisplayDevice::getFormat() const {
- return mFormat;
- }
- EGLSurface DisplayDevice::getEGLSurface() const {
- return mSurface;
- }
- void DisplayDevice::setDisplayName(const String8& displayName) {
- if (!displayName.isEmpty()) {
- // never override the name with an empty name
- mDisplayName = displayName;
- }
- }
- uint32_t DisplayDevice::getPageFlipCount() const {
- return mPageFlipCount;
- }
- status_t DisplayDevice::compositionComplete() const {
- return mDisplaySurface->compositionComplete();
- }
- void DisplayDevice::flip(const Region& dirty) const
- {
- mFlinger->getRenderEngine().checkErrors();
- if (kEGLAndroidSwapRectangle) {
- if (mFlags & SWAP_RECTANGLE) {
- const Region newDirty(dirty.intersect(bounds()));
- const Rect b(newDirty.getBounds());
- eglSetSwapRectangleANDROID(mDisplay, mSurface,
- b.left, b.top, b.width(), b.height());
- }
- }
- mPageFlipCount++;
- }
- status_t DisplayDevice::beginFrame(bool mustRecompose) const {
- return mDisplaySurface->beginFrame(mustRecompose);
- }
- status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
- DisplaySurface::CompositionType compositionType;
- bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
- bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
- if (haveGles && haveHwc) {
- compositionType = DisplaySurface::COMPOSITION_MIXED;
- } else if (haveGles) {
- compositionType = DisplaySurface::COMPOSITION_GLES;
- } else if (haveHwc) {
- compositionType = DisplaySurface::COMPOSITION_HWC;
- } else {
- // Nothing to do -- when turning the screen off we get a frame like
- // this. Call it a HWC frame since we won't be doing any GLES work but
- // will do a prepare/set cycle.
- compositionType = DisplaySurface::COMPOSITION_HWC;
- }
- return mDisplaySurface->prepareFrame(compositionType);
- }
- void DisplayDevice::swapBuffers(HWComposer& hwc) const {
- // We need to call eglSwapBuffers() if:
- // (1) we don't have a hardware composer, or
- // (2) we did GLES composition this frame, and either
- // (a) we have framebuffer target support (not present on legacy
- // devices, where HWComposer::commit() handles things); or
- // (b) this is a virtual display
- if (hwc.initCheck() != NO_ERROR ||
- (hwc.hasGlesComposition(mHwcDisplayId) &&
- (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
- EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
- if (!success) {
- EGLint error = eglGetError();
- if (error == EGL_CONTEXT_LOST ||
- mType == DisplayDevice::DISPLAY_PRIMARY) {
- LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
- mDisplay, mSurface, error);
- } else {
- ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
- mDisplay, mSurface, error);
- }
- }
- }
- status_t result = mDisplaySurface->advanceFrame();
- if (result != NO_ERROR) {
- ALOGE("[%s] failed pushing new frame to HWC: %d",
- mDisplayName.string(), result);
- }
- }
- void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
- if (hwc.initCheck() == NO_ERROR) {
- mDisplaySurface->onFrameCommitted();
- }
- }
- uint32_t DisplayDevice::getFlags() const
- {
- return mFlags;
- }
- EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
- EGLBoolean result = EGL_TRUE;
- EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
- if (sur != mSurface) {
- result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
- if (result == EGL_TRUE) {
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- eglSwapInterval(dpy, 0);
- }
- }
- setViewportAndProjection();
- return result;
- }
- void DisplayDevice::setViewportAndProjection() const {
- size_t w = mDisplayWidth;
- size_t h = mDisplayHeight;
- Rect sourceCrop(0, 0, w, h);
- mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
- false, Transform::ROT_0);
- }
- // ----------------------------------------------------------------------------
- void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
- mVisibleLayersSortedByZ = layers;
- mSecureLayerVisible = false;
- size_t count = layers.size();
- for (size_t i=0 ; i<count ; i++) {
- const sp<Layer>& layer(layers[i]);
- if (layer->isSecure()) {
- mSecureLayerVisible = true;
- }
- }
- }
- const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
- return mVisibleLayersSortedByZ;
- }
- bool DisplayDevice::getSecureLayerVisible() const {
- return mSecureLayerVisible;
- }
- Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
- Region dirty;
- if (repaintEverything) {
- dirty.set(getBounds());
- } else {
- const Transform& planeTransform(mGlobalTransform);
- dirty = planeTransform.transform(this->dirtyRegion);
- dirty.andSelf(getBounds());
- }
- return dirty;
- }
- // ----------------------------------------------------------------------------
- void DisplayDevice::setPowerMode(int mode) {
- mPowerMode = mode;
- }
- int DisplayDevice::getPowerMode() const {
- return mPowerMode;
- }
- bool DisplayDevice::isDisplayOn() const {
- return (mPowerMode != HWC_POWER_MODE_OFF);
- }
- // ----------------------------------------------------------------------------
- void DisplayDevice::setActiveConfig(int mode) {
- mActiveConfig = mode;
- }
- int DisplayDevice::getActiveConfig() const {
- return mActiveConfig;
- }
- // ----------------------------------------------------------------------------
- void DisplayDevice::setLayerStack(uint32_t stack) {
- mLayerStack = stack;
- dirtyRegion.set(bounds());
- }
- // ----------------------------------------------------------------------------
- uint32_t DisplayDevice::getOrientationTransform() const {
- uint32_t transform = 0;
- switch (mOrientation) {
- case DisplayState::eOrientationDefault:
- transform = Transform::ROT_0;
- break;
- case DisplayState::eOrientation90:
- transform = Transform::ROT_90;
- break;
- case DisplayState::eOrientation180:
- transform = Transform::ROT_180;
- break;
- case DisplayState::eOrientation270:
- transform = Transform::ROT_270;
- break;
- }
- return transform;
- }
- status_t DisplayDevice::orientationToTransfrom(
- int orientation, int w, int h, Transform* tr)
- {
- uint32_t flags = 0;
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.sf.hwrotation", value, "0");
- int additionalRot = atoi(value);
- if (additionalRot && mType == DISPLAY_PRIMARY) {
- additionalRot /= 90;
- if (orientation == DisplayState::eOrientationUnchanged) {
- orientation = additionalRot;
- } else {
- orientation += additionalRot;
- orientation %= 4;
- }
- }
- switch (orientation) {
- case DisplayState::eOrientationDefault:
- flags = Transform::ROT_0;
- break;
- case DisplayState::eOrientation90:
- flags = Transform::ROT_90;
- break;
- case DisplayState::eOrientation180:
- flags = Transform::ROT_180;
- break;
- case DisplayState::eOrientation270:
- flags = Transform::ROT_270;
- break;
- default:
- return BAD_VALUE;
- }
- if (DISPLAY_PRIMARY == mHwcDisplayId) {
- flags = flags ^ getPanelMountFlip();
- }
- tr->set(flags, w, h);
- return NO_ERROR;
- }
- void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
- dirtyRegion.set(getBounds());
- if (mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mDisplay, mSurface);
- mSurface = EGL_NO_SURFACE;
- }
- mDisplaySurface->resizeBuffers(newWidth, newHeight);
- ANativeWindow* const window = mNativeWindow.get();
- mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
- eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mDisplayWidth);
- eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
- LOG_FATAL_IF(mDisplayWidth != newWidth,
- "Unable to set new width to %d", newWidth);
- LOG_FATAL_IF(mDisplayHeight != newHeight,
- "Unable to set new height to %d", newHeight);
- }
- void DisplayDevice::setProjection(int orientation,
- const Rect& newViewport, const Rect& newFrame) {
- Rect viewport(newViewport);
- Rect frame(newFrame);
- const int w = mDisplayWidth;
- const int h = mDisplayHeight;
- Transform R;
- DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
- if (!frame.isValid()) {
- // the destination frame can be invalid if it has never been set,
- // in that case we assume the whole display frame.
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.sf.hwrotation", value, "0");
- int additionalRot = atoi(value);
- if (additionalRot == 90 || additionalRot == 270) {
- frame = Rect(h, w);
- } else {
- frame = Rect(w, h);
- }
- }
- if (viewport.isEmpty()) {
- // viewport can be invalid if it has never been set, in that case
- // we assume the whole display size.
- // it's also invalid to have an empty viewport, so we handle that
- // case in the same way.
- viewport = Rect(w, h);
- if (R.getOrientation() & Transform::ROT_90) {
- // viewport is always specified in the logical orientation
- // of the display (ie: post-rotation).
- swap(viewport.right, viewport.bottom);
- }
- }
- dirtyRegion.set(getBounds());
- Transform TL, TP, S;
- float src_width = viewport.width();
- float src_height = viewport.height();
- float dst_width = frame.width();
- float dst_height = frame.height();
- if (src_width != dst_width || src_height != dst_height) {
- float sx = dst_width / src_width;
- float sy = dst_height / src_height;
- S.set(sx, 0, 0, sy);
- }
- float src_x = viewport.left;
- float src_y = viewport.top;
- float dst_x = frame.left;
- float dst_y = frame.top;
- TL.set(-src_x, -src_y);
- TP.set(dst_x, dst_y);
- // The viewport and frame are both in the logical orientation.
- // Apply the logical translation, scale to physical size, apply the
- // physical translation and finally rotate to the physical orientation.
- mGlobalTransform = R * TP * S * TL;
- const uint8_t type = mGlobalTransform.getType();
- mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
- (type >= Transform::SCALE));
- mScissor = mGlobalTransform.transform(viewport);
- if (mScissor.isEmpty()) {
- mScissor = getBounds();
- }
- mOrientation = orientation;
- mViewport = viewport;
- mFrame = frame;
- }
- void DisplayDevice::dump(String8& result) const {
- const Transform& tr(mGlobalTransform);
- result.appendFormat(
- "+ DisplayDevice: %s\n"
- " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
- "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
- " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
- "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
- mDisplayName.string(), mType, mHwcDisplayId,
- mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
- mOrientation, tr.getType(), getPageFlipCount(),
- mIsSecure, mSecureLayerVisible, mPowerMode, mActiveConfig,
- mVisibleLayersSortedByZ.size(),
- mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
- mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
- mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
- tr[0][0], tr[1][0], tr[2][0],
- tr[0][1], tr[1][1], tr[2][1],
- tr[0][2], tr[1][2], tr[2][2]);
- String8 surfaceDump;
- mDisplaySurface->dumpAsString(surfaceDump);
- result.append(surfaceDump);
- }
|