OSDN Git Service

SurfaceFlinger: add support for secure displays
[android-x86/frameworks-native.git] / services / surfaceflinger / DisplayDevice.cpp
index 4cae692..ce98b67 100644 (file)
@@ -38,6 +38,7 @@
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
 
+#include "clz.h"
 #include "DisplayDevice.h"
 #include "GLExtensions.h"
 #include "SurfaceFlinger.h"
@@ -68,12 +69,14 @@ void checkGLErrors()
 
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
-        int display,
+        DisplayType type,
+        bool isSecure,
+        const wp<IBinder>& displayToken,
         const sp<ANativeWindow>& nativeWindow,
         const sp<FramebufferSurface>& framebufferSurface,
         EGLConfig config)
     : mFlinger(flinger),
-      mId(display),
+      mType(type), mHwcDisplayId(-1),
       mNativeWindow(nativeWindow),
       mFramebufferSurface(framebufferSurface),
       mDisplay(EGL_NO_DISPLAY),
@@ -82,10 +85,11 @@ DisplayDevice::DisplayDevice(
       mDisplayWidth(), mDisplayHeight(), mFormat(),
       mFlags(),
       mPageFlipCount(),
+      mIsSecure(isSecure),
       mSecureLayerVisible(false),
       mScreenAcquired(false),
-      mOrientation(),
-      mLayerStack(0)
+      mLayerStack(0),
+      mOrientation()
 {
     init(config);
 }
@@ -139,9 +143,38 @@ void DisplayDevice::init(EGLConfig config)
     mSurface = surface;
     mFormat  = format;
     mPageFlipCount = 0;
+    mViewport.makeInvalid();
+    mFrame.makeInvalid();
+
+    // external displays are always considered enabled
+    mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
+
+    // get an h/w composer ID
+    mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
+
+    // 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;
+    }
 
     // initialize the display orientation transform.
-    DisplayDevice::setOrientation(DisplayState::eOrientationDefault);
+    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
+}
+
+void DisplayDevice::setDisplayName(const String8& displayName) {
+    if (!displayName.isEmpty()) {
+        // never override the name with an empty name
+        mDisplayName = displayName;
+    }
 }
 
 uint32_t DisplayDevice::getPageFlipCount() const {
@@ -170,28 +203,80 @@ void DisplayDevice::flip(const Region& dirty) const
                 b.left, b.top, b.width(), b.height());
     } 
 #endif
-    
+
     mPageFlipCount++;
 }
 
-uint32_t DisplayDevice::getFlags() const
-{
-    return mFlags;
+void DisplayDevice::swapBuffers(HWComposer& hwc) const {
+    EGLBoolean success = EGL_TRUE;
+    if (hwc.initCheck() != NO_ERROR) {
+        // no HWC, we call eglSwapBuffers()
+        success = eglSwapBuffers(mDisplay, mSurface);
+    } else {
+        // We have a valid HWC, but not all displays can use it, in particular
+        // the virtual displays are on their own.
+        // TODO: HWC 1.2 will allow virtual displays
+        if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
+            // always call eglSwapBuffers() for virtual displays
+            success = eglSwapBuffers(mDisplay, mSurface);
+        } else if (hwc.supportsFramebufferTarget()) {
+            // as of hwc 1.1 we always call eglSwapBuffers if we have some
+            // GLES layers
+            if (hwc.hasGlesComposition(mType)) {
+                success = eglSwapBuffers(mDisplay, mSurface);
+            }
+        } else {
+            // HWC doesn't have the framebuffer target, we don't call
+            // eglSwapBuffers(), since this is handled by HWComposer::commit().
+        }
+    }
+
+    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);
+        }
+    }
 }
 
-void DisplayDevice::dump(String8& res) const
-{
-    if (mFramebufferSurface != NULL) {
-        mFramebufferSurface->dump(res);
+void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
+    if (hwc.initCheck() == NO_ERROR) {
+        if (hwc.supportsFramebufferTarget()) {
+            int fd = hwc.getAndResetReleaseFenceFd(mType);
+            mFramebufferSurface->setReleaseFenceFd(fd);
+        }
     }
 }
 
-void DisplayDevice::makeCurrent(const sp<const DisplayDevice>& hw, EGLContext ctx) {
+uint32_t DisplayDevice::getFlags() const
+{
+    return mFlags;
+}
+
+EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
+        const sp<const DisplayDevice>& hw, EGLContext ctx) {
+    EGLBoolean result = EGL_TRUE;
     EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
     if (sur != hw->mSurface) {
-        EGLDisplay dpy = eglGetCurrentDisplay();
-        eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
+        result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
+        if (result == EGL_TRUE) {
+            setViewportAndProjection(hw);
+        }
     }
+    return result;
+}
+
+void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) {
+    GLsizei w = hw->mDisplayWidth;
+    GLsizei h = hw->mDisplayHeight;
+    glViewport(0, 0, w, h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    // put the origin in the left-bottom corner
+    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
+    glMatrixMode(GL_MODELVIEW);
 }
 
 // ----------------------------------------------------------------------------
@@ -207,7 +292,7 @@ void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& lay
     }
 }
 
-Vector< sp<LayerBase> > DisplayDevice::getVisibleLayersSortedByZ() const {
+const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
     return mVisibleLayersSortedByZ;
 }
 
@@ -215,6 +300,18 @@ 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;
+}
+
 // ----------------------------------------------------------------------------
 
 bool DisplayDevice::canDraw() const {
@@ -266,18 +363,95 @@ status_t DisplayDevice::orientationToTransfrom(
     return NO_ERROR;
 }
 
-status_t DisplayDevice::setOrientation(int orientation) {
+void DisplayDevice::setProjection(int orientation,
+        const Rect& viewport, const Rect& frame) {
+    mOrientation = orientation;
+    mViewport = viewport;
+    mFrame = frame;
+    updateGeometryTransform();
+}
+
+void DisplayDevice::updateGeometryTransform() {
     int w = mDisplayWidth;
     int h = mDisplayHeight;
+    Transform TL, TP, R, S;
+    if (DisplayDevice::orientationToTransfrom(
+            mOrientation, w, h, &R) == NO_ERROR) {
+        dirtyRegion.set(bounds());
+
+        Rect viewport(mViewport);
+        Rect frame(mFrame);
+
+        if (!frame.isValid()) {
+            // the destination frame can be invalid if it has never been set,
+            // in that case we assume the whole display frame.
+            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);
+            }
+        }
 
-    DisplayDevice::orientationToTransfrom(
-            orientation, w, h, &mGlobalTransform);
-    if (orientation & DisplayState::eOrientationSwapMask) {
-        int tmp = w;
-        w = h;
-        h = tmp;
+        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));
+    }
+}
+
+void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
+    const Transform& tr(mGlobalTransform);
+    snprintf(buffer, SIZE,
+        "+ DisplayDevice: %s\n"
+        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
+        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
+        "   v:[%d,%d,%d,%d], f:[%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,
+        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
+        mOrientation, tr.getType(), getPageFlipCount(),
+        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
+        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
+        mFrame.left, mFrame.top, mFrame.right, mFrame.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]);
+
+    result.append(buffer);
+
+    String8 fbtargetDump;
+    if (mFramebufferSurface != NULL) {
+        mFramebufferSurface->dump(fbtargetDump);
+        result.append(fbtargetDump);
     }
-    mOrientation = orientation;
-    dirtyRegion.set(bounds());
-    return NO_ERROR;
 }