diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 4cae6926f..a379111c7 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -140,6 +140,9 @@ void DisplayDevice::init(EGLConfig config) mFormat = format; mPageFlipCount = 0; + // external displays are always considered enabled + mScreenAcquired = mId >= DisplayDevice::DISPLAY_ID_COUNT; + // initialize the display orientation transform. DisplayDevice::setOrientation(DisplayState::eOrientationDefault); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index c9df7a426..a3ec3522b 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -334,7 +334,8 @@ void HWComposer::eventControl(int event, int enabled) { } } -status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { // FIXME: handle multiple displays +status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { + // FIXME: handle multiple displays if (uint32_t(id) >= MAX_DISPLAYS) return BAD_INDEX; @@ -360,6 +361,15 @@ status_t HWComposer::prepare() const { int err = hwcPrepare(mHwc, 1, const_cast(mLists)); if (err == NO_ERROR) { + + // here we're just making sure that "skip" layers are set + // to HWC_FRAMEBUFFER and we're also counting how many layers + // we have of each type. + // It would be nice if we could get rid of this entirely, which I + // think is almost possible. + + // TODO: must handle multiple displays here + size_t numOVLayers = 0; size_t numFBLayers = 0; size_t count = getNumLayers(0); @@ -397,7 +407,15 @@ status_t HWComposer::prepare() const { return (status_t)err; } -size_t HWComposer::getLayerCount(int32_t id, int type) const { // FIXME: handle multiple displays +size_t HWComposer::getLayerCount(int32_t id, int type) const { + // FIXME: handle multiple displays + if (uint32_t(id) >= MAX_DISPLAYS) { + // FIXME: in practice this is only use to know + // if we have at least one layer of type. + return (type == HWC_FRAMEBUFFER) ? 1 : 0; + } + + switch (type) { case HWC_OVERLAY: return mNumOVLayers; @@ -623,7 +641,11 @@ public: /* * returns an iterator initialized at a given index in the layer list */ -HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) { // FIXME: handle multiple displays +HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) { + // FIXME: handle multiple displays + if (uint32_t(id) >= MAX_DISPLAYS) + return LayerListIterator(); + if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0])) return LayerListIterator(); if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) { @@ -638,14 +660,14 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in /* * returns an iterator on the beginning of the layer list */ -HWComposer::LayerListIterator HWComposer::begin(int32_t id) { // FIXME: handle multiple displays +HWComposer::LayerListIterator HWComposer::begin(int32_t id) { return getLayerIterator(id, 0); } /* * returns an iterator on the end of the layer list */ -HWComposer::LayerListIterator HWComposer::end(int32_t id) { // FIXME: handle multiple displays +HWComposer::LayerListIterator HWComposer::end(int32_t id) { return getLayerIterator(id, getNumLayers(id)); } diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index e6189f728..2311e6db4 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -426,10 +426,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const snprintf(buffer, SIZE, " " - "z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " + "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, " "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, + s.z, s.layerStack, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, s.active.crop.left, s.active.crop.top, s.active.crop.right, s.active.crop.bottom, isOpaque(), needsDithering(), contentDirty, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 70d6ddb24..63f3d91f0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -95,8 +95,7 @@ SurfaceFlinger::SurfaceFlinger() mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), - mBootFinished(false), - mExternalDisplaySurface(EGL_NO_SURFACE) + mBootFinished(false) { ALOGI("SurfaceFlinger is starting"); @@ -555,40 +554,34 @@ sp SurfaceFlinger::createDisplayEventConnection() { return mEventThread->createEventConnection(); } -void SurfaceFlinger::connectDisplay(const sp display) { - EGLSurface result = EGL_NO_SURFACE; - EGLSurface old_surface = EGL_NO_SURFACE; - sp stc; +void SurfaceFlinger::connectDisplay(const sp surface) { - if (display != NULL) { - stc = new SurfaceTextureClient(display); - result = eglCreateWindowSurface(mEGLDisplay, - mEGLConfig, (EGLNativeWindowType)stc.get(), NULL); - ALOGE_IF(result == EGL_NO_SURFACE, - "eglCreateWindowSurface failed (ISurfaceTexture=%p)", - display.get()); + sp token; + { // scope for the lock + Mutex::Autolock _l(mStateLock); + token = mExtDisplayToken; + } + + if (token == 0) { + token = createDisplay(); } { // scope for the lock Mutex::Autolock _l(mStateLock); - old_surface = mExternalDisplaySurface; - mExternalDisplayNativeWindow = stc; - mExternalDisplaySurface = result; - ALOGD("mExternalDisplaySurface = %p", result); - } + if (surface == 0) { + // release our current display. we're guarantee to have + // a reference to it (token), while we hold the lock + mExtDisplayToken = 0; + } else { + mExtDisplayToken = token; + } - if (old_surface != EGL_NO_SURFACE) { - // Note: EGL allows to destroy an object while its current - // it will fail to become current next time though. - eglDestroySurface(mEGLDisplay, old_surface); + DisplayDeviceState& info(mCurrentState.displays.editValueFor(token)); + info.surface = surface; + setTransactionFlags(eDisplayTransactionNeeded); } } -EGLSurface SurfaceFlinger::getExternalDisplaySurface() const { - Mutex::Autolock _l(mStateLock); - return mExternalDisplaySurface; -} - // ---------------------------------------------------------------------------- void SurfaceFlinger::waitForEvent() { @@ -757,49 +750,6 @@ void SurfaceFlinger::handleMessageRefresh() { } postFramebuffer(); - - -#if 1 - // render to the external display if we have one - EGLSurface externalDisplaySurface = getExternalDisplaySurface(); - if (externalDisplaySurface != EGL_NO_SURFACE) { - EGLSurface cur = eglGetCurrentSurface(EGL_DRAW); - EGLBoolean success = eglMakeCurrent(eglGetCurrentDisplay(), - externalDisplaySurface, externalDisplaySurface, - eglGetCurrentContext()); - - ALOGE_IF(!success, "eglMakeCurrent -> external failed"); - - if (success) { - // redraw the screen entirely... - glDisable(GL_TEXTURE_EXTERNAL_OES); - glDisable(GL_TEXTURE_2D); - glClearColor(0,0,0,1); - glClear(GL_COLOR_BUFFER_BIT); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - const sp& hw(getDisplayDevice(0)); - const Vector< sp >& layers( hw->getVisibleLayersSortedByZ() ); - const size_t count = layers.size(); - for (size_t i=0 ; i& layer(layers[i]); - layer->draw(hw); - } - - success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface); - ALOGE_IF(!success, "external display eglSwapBuffers failed"); - - hw->compositionComplete(); - } - - success = eglMakeCurrent(eglGetCurrentDisplay(), - cur, cur, eglGetCurrentContext()); - - ALOGE_IF(!success, "eglMakeCurrent -> internal failed"); - } -#endif - } void SurfaceFlinger::postFramebuffer() @@ -830,6 +780,10 @@ void SurfaceFlinger::postFramebuffer() if (hwc.initCheck() == NO_ERROR) { // FIXME: eventually commit() won't take arguments + // FIXME: EGL spec says: + // "surface must be bound to the calling thread's current context, + // for the current rendering API." + DisplayDevice::makeCurrent(getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext); hwc.commit(mEGLDisplay, getDefaultDisplayDevice()->getEGLSurface()); } @@ -844,14 +798,22 @@ void SurfaceFlinger::postFramebuffer() for (size_t i = 0; cur != end && i < count; ++i, ++cur) { currentLayers[i]->onLayerDisplayed(hw, &*cur); } - } else { + } + + // FIXME: we need to call eglSwapBuffers() on displays that have + // GL composition and only on those. + // however, currently hwc.commit() already does that for the main + // display and never for the other ones + if (hw->getDisplayId() >= DisplayDevice::DISPLAY_ID_COUNT) { + // FIXME: EGL spec says: + // "surface must be bound to the calling thread's current context, + // for the current rendering API." + DisplayDevice::makeCurrent(hw, mEGLContext); eglSwapBuffers(mEGLDisplay, hw->getEGLSurface()); for (size_t i = 0; i < count; i++) { currentLayers[i]->onLayerDisplayed(hw, NULL); } } - - // FIXME: we need to call eglSwapBuffers() on displays that have GL composition } mLastSwapBufferTime = systemTime() - now; @@ -967,7 +929,6 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // (ie: in current state but not in drawing state) for (size_t i=0 ; i stc( new SurfaceTextureClient(state.surface)); @@ -1954,6 +1915,26 @@ void SurfaceFlinger::dumpAllLocked( layer->shortDump(result, buffer, SIZE); } + /* + * Dump Display state + */ + + for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); + snprintf(buffer, SIZE, + "+ DisplayDevice[%u]\n" + " id=%x, layerStack=%u, (%4dx%4d), orient=%2d, tr=%08x, " + "flips=%u, secure=%d, numLayers=%u\n", + dpy, + hw->getDisplayId(), hw->getLayerStack(), + hw->getWidth(), hw->getHeight(), + hw->getOrientation(), hw->getTransform().getType(), + hw->getPageFlipCount(), + hw->getSecureLayerVisible(), + hw->getVisibleLayersSortedByZ().size()); + result.append(buffer); + } + /* * Dump SurfaceFlinger global state */ diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6438beebd..4831d9d8d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -428,9 +428,7 @@ private: * Feature prototyping */ - EGLSurface getExternalDisplaySurface() const; - sp mExternalDisplayNativeWindow; - EGLSurface mExternalDisplaySurface; + sp mExtDisplayToken; }; // ---------------------------------------------------------------------------