X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=services%2Fsurfaceflinger%2FDisplayDevice.cpp;h=ce98b6769cb9685f66c3a09999a97613c01f4535;hb=dd3cb84cfbe8068790c6233b5829fae9c4a0ee93;hp=228944422339c1d48c346060103692d19787e059;hpb=729f48082e2c7660e94830e52006f7af4efb747a;p=android-x86%2Fframeworks-native.git diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 2289444223..ce98b6769c 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -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& flinger, - int display, + DisplayType type, + bool isSecure, + const wp& displayToken, const sp& nativeWindow, const sp& 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,12 +143,38 @@ void DisplayDevice::init(EGLConfig config) mSurface = surface; mFormat = format; mPageFlipCount = 0; + mViewport.makeInvalid(); + mFrame.makeInvalid(); // external displays are always considered enabled - mScreenAcquired = mId >= DisplayDevice::DISPLAY_ID_COUNT; + 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 { @@ -173,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& hw, EGLContext ctx) { +uint32_t DisplayDevice::getFlags() const +{ + return mFlags; +} + +EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, + const sp& 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& 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); } // ---------------------------------------------------------------------------- @@ -210,7 +292,7 @@ void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp >& lay } } -Vector< sp > DisplayDevice::getVisibleLayersSortedByZ() const { +const Vector< sp >& DisplayDevice::getVisibleLayersSortedByZ() const { return mVisibleLayersSortedByZ; } @@ -220,10 +302,10 @@ bool DisplayDevice::getSecureLayerVisible() const { Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { Region dirty; - const Transform& planeTransform(mGlobalTransform); if (repaintEverything) { dirty.set(getBounds()); } else { + const Transform& planeTransform(mGlobalTransform); dirty = planeTransform.transform(this->dirtyRegion); dirty.andSelf(getBounds()); } @@ -281,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); + } - DisplayDevice::orientationToTransfrom( - orientation, w, h, &mGlobalTransform); - if (orientation & DisplayState::eOrientationSwapMask) { - int tmp = w; - w = h; - h = tmp; + 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); + } + } + + 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; }