From da27af9832a0170f1fc40ef3f21371c4d30d21b3 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 13 Sep 2012 18:17:13 -0700 Subject: [PATCH] add support hwc 1.1 Bug: 7124069 Change-Id: I53d705105c4ad8954d3f50ee4f4c8b7ec936b871 --- services/surfaceflinger/DisplayDevice.cpp | 26 +++ services/surfaceflinger/DisplayDevice.h | 5 + .../DisplayHardware/FramebufferSurface.cpp | 39 ++-- .../DisplayHardware/FramebufferSurface.h | 16 +- .../DisplayHardware/HWComposer.cpp | 209 ++++++++++++++---- .../DisplayHardware/HWComposer.h | 20 +- services/surfaceflinger/Layer.cpp | 4 + services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/LayerBase.cpp | 5 + services/surfaceflinger/LayerBase.h | 5 + services/surfaceflinger/SurfaceFlinger.cpp | 42 ++-- 11 files changed, 283 insertions(+), 89 deletions(-) diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 2c06a0b55..72f73f78a 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -183,6 +183,32 @@ void DisplayDevice::flip(const Region& dirty) const mPageFlipCount++; } +void DisplayDevice::swapBuffers(HWComposer& hwc) const { + if (hwc.initCheck() != NO_ERROR) { + // no HWC, we call eglSwapBuffers() + eglSwapBuffers(mDisplay, mSurface); + } else { + if (hwc.hasGlesComposition(mType)) { + if (hwc.supportsFramebufferTarget() || + mType >= DisplayDevice::DISPLAY_VIRTUAL) { + // as of hwc 1.1 we always call eglSwapBuffers, however, + // on older versions of HWC, we need to call it only on + // virtual displays + eglSwapBuffers(mDisplay, mSurface); + } + } + } +} + +void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { + if (hwc.initCheck() == NO_ERROR) { + if (hwc.supportsFramebufferTarget()) { + int fd = hwc.getAndResetReleaseFenceFd(mType); + mFramebufferSurface->setReleaseFenceFd(fd); + } + } +} + uint32_t DisplayDevice::getFlags() const { return mFlags; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8122b9dc5..4a3f0a0aa 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -40,6 +40,7 @@ class DisplayInfo; class FramebufferSurface; class LayerBase; class SurfaceFlinger; +class HWComposer; class DisplayDevice : public LightRefBase { @@ -106,8 +107,12 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp& getDisplayToken() const { return mDisplayToken; } + void swapBuffers(HWComposer& hwc) const; status_t compositionComplete() const; + // called after h/w composer has completed its set() call + void onSwapBuffersCompleted(HWComposer& hwc) const; + Rect getBounds() const { return Rect(mDisplayWidth, mDisplayHeight); } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 92a3fcc7b..a4f8fb631 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -74,15 +74,13 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc) : mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS); } -status_t FramebufferSurface::nextBuffer(sp* buffer) { +status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& outFence) { Mutex::Autolock lock(mMutex); BufferQueue::BufferItem item; status_t err = acquireBufferLocked(&item); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { - if (buffer != NULL) { - *buffer = mCurrentBuffer; - } + outBuffer = mCurrentBuffer; return NO_ERROR; } else if (err != NO_ERROR) { ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err); @@ -107,32 +105,24 @@ status_t FramebufferSurface::nextBuffer(sp* buffer) { return err; } } - mCurrentBufferSlot = item.mBuf; mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; - if (item.mFence != NULL) { - item.mFence->wait(Fence::TIMEOUT_NEVER); - } - - if (buffer != NULL) { - *buffer = mCurrentBuffer; - } - + outFence = item.mFence; + outBuffer = mCurrentBuffer; return NO_ERROR; } // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl. void FramebufferSurface::onFrameAvailable() { - // XXX: The following code is here temporarily as part of the transition - // away from the framebuffer HAL. sp buf; - status_t err = nextBuffer(&buf); + sp acquireFence; + status_t err = nextBuffer(buf, acquireFence); if (err != NO_ERROR) { - ALOGE("error latching next FramebufferSurface buffer: %s (%d)", + ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)", strerror(-err), err); return; } - err = mHwc.fbPost(buf->handle); + err = mHwc.fbPost(0, acquireFence, buf); // FIXME: use real display id if (err != NO_ERROR) { ALOGE("error posting framebuffer: %d", err); } @@ -145,6 +135,19 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) { } } +status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) { + status_t err = NO_ERROR; + if (fenceFd >= 0) { + sp fence(new Fence(fenceFd)); + if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) { + status_t err = addReleaseFence(mCurrentBufferSlot, fence); + ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)", + strerror(-err), err); + } + } + return err; +} + status_t FramebufferSurface::setUpdateRectangle(const Rect& r) { return INVALID_OPERATION; diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index fd7c5203d..717a3f16f 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -44,10 +44,13 @@ public: virtual void dump(String8& result); - // nextBuffer waits for and then latches the next buffer from the - // BufferQueue and releases the previously latched buffer to the - // BufferQueue. The new buffer is returned in the 'buffer' argument. - status_t nextBuffer(sp* buffer); + // setReleaseFenceFd stores a fence file descriptor that will signal when the + // current buffer is no longer being read. This fence will be returned to + // the producer when the current buffer is released by updateTexImage(). + // Multiple fences can be set for a given buffer; they will be merged into + // a single union fence. The SurfaceTexture will close the file descriptor + // when finished with it. + status_t setReleaseFenceFd(int fenceFd); private: virtual ~FramebufferSurface() { }; // this class cannot be overloaded @@ -55,6 +58,11 @@ private: virtual void onFrameAvailable(); virtual void freeBufferLocked(int slotIndex); + // nextBuffer waits for and then latches the next buffer from the + // BufferQueue and releases the previously latched buffer to the + // BufferQueue. The new buffer is returned in the 'buffer' argument. + status_t nextBuffer(sp& outBuffer, sp& outFence); + // mCurrentBufferIndex is the slot index of the current buffer or // INVALID_BUFFER_SLOT to indicate that either there is no current buffer // or the buffer is not associated with a slot. diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 81640afd5..9c04fc035 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include "LayerBase.h" #include "HWComposer.h" #include "SurfaceFlinger.h" +#include namespace android { @@ -111,6 +113,14 @@ HWComposer::HWComposer( loadFbHalModule(); loadHwcModule(); + if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { + // close FB HAL if we don't needed it. + // FIXME: this is temporary until we're not forced to open FB HAL + // before HWC. + framebuffer_close(mFbDev); + mFbDev = NULL; + } + // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory. if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) && !mFbDev) { @@ -310,7 +320,7 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = { #define ANDROID_DENSITY_XHIGH 320 void HWComposer::queryDisplayProperties(int disp) { - ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); + LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); // use zero as default value for unspecified attributes int32_t values[NUM_DISPLAY_ATTRIBUTES - 1]; @@ -319,7 +329,11 @@ void HWComposer::queryDisplayProperties(int disp) { uint32_t config; size_t numConfigs = 1; status_t err = mHwc->getDisplayConfigs(mHwc, disp, &config, &numConfigs); + LOG_ALWAYS_FATAL_IF(err, "getDisplayAttributes failed (%s)", strerror(-err)); + if (err == NO_ERROR) { + ALOGD("config=%d, numConfigs=%d, NUM_DISPLAY_ATTRIBUTES=%d", + config, numConfigs, NUM_DISPLAY_ATTRIBUTES); mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES, values); } @@ -343,8 +357,8 @@ void HWComposer::queryDisplayProperties(int disp) { mDisplayData[disp].ydpi = values[i] / 1000.0f; break; default: - ALOG_ASSERT(false, "unknown display attribute %#x", - DISPLAY_ATTRIBUTES[i]); + ALOG_ASSERT(false, "unknown display attribute[%d] %#x", + i, DISPLAY_ATTRIBUTES[i]); break; } } @@ -439,13 +453,35 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { if (mHwc) { DisplayData& disp(mDisplayData[id]); + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { + // we need space for the HWC_FRAMEBUFFER_TARGET + numLayers++; + } if (disp.capacity < numLayers || disp.list == NULL) { - const size_t size = sizeof(hwc_display_contents_1_t) + size_t size = sizeof(hwc_display_contents_1_t) + numLayers * sizeof(hwc_layer_1_t); free(disp.list); disp.list = (hwc_display_contents_1_t*)malloc(size); disp.capacity = numLayers; } + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { + disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1]; + memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t)); + const hwc_rect_t r = { 0, 0, disp.width, disp.height }; + disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET; + disp.framebufferTarget->hints = 0; + disp.framebufferTarget->flags = 0; + disp.framebufferTarget->handle = disp.fbTargetHandle; + disp.framebufferTarget->transform = 0; + disp.framebufferTarget->blending = HWC_BLENDING_PREMULT; + disp.framebufferTarget->sourceCrop = r; + disp.framebufferTarget->displayFrame = r; + disp.framebufferTarget->visibleRegionScreen.numRects = 1; + disp.framebufferTarget->visibleRegionScreen.rects = + &disp.framebufferTarget->displayFrame; + disp.framebufferTarget->acquireFenceFd = -1; + disp.framebufferTarget->releaseFenceFd = -1; + } disp.list->retireFenceFd = -1; disp.list->flags = HWC_GEOMETRY_CHANGED; disp.list->numHwLayers = numLayers; @@ -453,9 +489,46 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { return NO_ERROR; } +status_t HWComposer::setFramebufferTarget(int32_t id, + const sp& acquireFence, const sp& buf) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) { + return BAD_INDEX; + } + DisplayData& disp(mDisplayData[id]); + if (!disp.framebufferTarget) { + // this should never happen, but apparently eglCreateWindowSurface() + // triggers a SurfaceTextureClient::queueBuffer() on some + // devices (!?) -- log and ignore. + ALOGE("HWComposer: framebufferTarget is null"); + CallStack stack; + stack.update(); + stack.dump(""); + return NO_ERROR; + } + + int acquireFenceFd = -1; + if (acquireFence != NULL) { + acquireFenceFd = acquireFence->dup(); + } + + // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd); + disp.fbTargetHandle = buf->handle; + disp.framebufferTarget->handle = disp.fbTargetHandle; + disp.framebufferTarget->acquireFenceFd = acquireFenceFd; + return NO_ERROR; +} + status_t HWComposer::prepare() { for (size_t i=0 ; icompositionType = HWC_FRAMEBUFFER_TARGET; + } + mLists[i] = disp.list; if (mLists[i]) { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { mLists[i]->outbuf = NULL; @@ -472,6 +545,8 @@ status_t HWComposer::prepare() { } int err = mHwc->prepare(mHwc, mNumDisplays, mLists); + ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err)); + 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 @@ -483,6 +558,10 @@ status_t HWComposer::prepare() { if (disp.list) { for (size_t i=0 ; inumHwLayers ; i++) { hwc_layer_1_t& l = disp.list->hwLayers[i]; + + //ALOGD("prepare: %d, type=%d, handle=%p", + // i, l.compositionType, l.handle); + if (l.flags & HWC_SKIP_LAYER) { l.compositionType = HWC_FRAMEBUFFER; } @@ -511,6 +590,21 @@ bool HWComposer::hasGlesComposition(int32_t id) const { return mDisplayData[id].hasFbComp; } +int HWComposer::getAndResetReleaseFenceFd(int32_t id) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return BAD_INDEX; + + int fd = INVALID_OPERATION; + if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { + const DisplayData& disp(mDisplayData[id]); + if (disp.framebufferTarget) { + fd = disp.framebufferTarget->releaseFenceFd; + disp.framebufferTarget->releaseFenceFd = -1; + } + } + return fd; +} + status_t HWComposer::commit() { int err = NO_ERROR; if (mHwc) { @@ -553,38 +647,43 @@ status_t HWComposer::acquire() const { return NO_ERROR; } -size_t HWComposer::getNumLayers(int32_t id) const { - if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) { - return 0; - } - return (mHwc && mDisplayData[id].list) ? - mDisplayData[id].list->numHwLayers : 0; -} - int HWComposer::getVisualID() const { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { - return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; + // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED + // is supported by the implementation. we can only be in this case + // if we have HWC 1.1 + return HAL_PIXEL_FORMAT_RGBA_8888; + //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; } else { return mFbDev->format; } } -int HWComposer::fbPost(buffer_handle_t buffer) { - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) { - return mFbDev->post(mFbDev, buffer); +bool HWComposer::supportsFramebufferTarget() const { + return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); +} + +int HWComposer::fbPost(int32_t id, + const sp& acquireFence, const sp& buffer) { + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { + return setFramebufferTarget(id, acquireFence, buffer); + } else { + if (acquireFence != NULL) { + acquireFence->wait(Fence::TIMEOUT_NEVER); + } + return mFbDev->post(mFbDev, buffer->handle); } - return NO_ERROR; } int HWComposer::fbCompositionComplete() { - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) { - if (mFbDev->compositionComplete) { - return mFbDev->compositionComplete(mFbDev); - } else { - return INVALID_OPERATION; - } + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) + return NO_ERROR; + + if (mFbDev->compositionComplete) { + return mFbDev->compositionComplete(mFbDev); + } else { + return INVALID_OPERATION; } - return NO_ERROR; } void HWComposer::fbDump(String8& result) { @@ -596,7 +695,6 @@ void HWComposer::fbDump(String8& result) { } } - /* * Helper template to implement a concrete HWCLayer * This holds the pointer to the concrete hwc layer type @@ -733,7 +831,22 @@ HWComposer::LayerListIterator HWComposer::begin(int32_t id) { * returns an iterator on the end of the layer list */ HWComposer::LayerListIterator HWComposer::end(int32_t id) { - return getLayerIterator(id, getNumLayers(id)); + size_t numLayers = 0; + if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) { + const DisplayData& disp(mDisplayData[id]); + if (mHwc && disp.list) { + numLayers = disp.list->numHwLayers; + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { + // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET, + // which we ignore when iterating through the layer list. + ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id); + if (numLayers) { + numLayers--; + } + } + } + } + return getLayerIterator(id, numLayers); } void HWComposer::dump(String8& result, char* buffer, size_t SIZE, @@ -747,27 +860,47 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, result.appendFormat(" id=%d, numHwLayers=%u, flags=%08x\n", i, disp.list->numHwLayers, disp.list->flags); result.append( - " type | handle | hints | flags | tr | blend | format | source crop | frame name \n" - "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); - // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] + " type | handle | hints | flags | tr | blend | format | source crop | frame name \n" + "------------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); + // " __________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] for (size_t i=0 ; inumHwLayers ; i++) { const hwc_layer_1_t&l = disp.list->hwLayers[i]; - const sp layer(visibleLayersSortedByZ[i]); int32_t format = -1; - if (layer->getLayer() != NULL) { - const sp& buffer( + String8 name("unknown"); + if (i < visibleLayersSortedByZ.size()) { + const sp& layer(visibleLayersSortedByZ[i]); + if (layer->getLayer() != NULL) { + const sp& buffer( layer->getLayer()->getActiveBuffer()); - if (buffer != NULL) { - format = buffer->getPixelFormat(); + if (buffer != NULL) { + format = buffer->getPixelFormat(); + } } + name = layer->getName(); } + + int type = l.compositionType; + if (type == HWC_FRAMEBUFFER_TARGET) { + name = "HWC_FRAMEBUFFER_TARGET"; + format = disp.format; + } + + static char const* compositionTypeName[] = { + "GLES", + "HWC", + "BACKGROUND", + "FB TARGET", + "UNKNOWN"}; + if (type >= NELEM(compositionTypeName)) + type = NELEM(compositionTypeName) - 1; + result.appendFormat( - " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", - l.compositionType ? "OVERLAY" : "FB", + " %10s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", + compositionTypeName[type], intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format, l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, - layer->getName().string()); + name.string()); } } } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index fe928c598..f253ecc76 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -36,6 +36,7 @@ extern "C" int clock_nanosleep(clockid_t clock_id, int flags, struct hwc_composer_device_1; struct hwc_display_contents_1; +struct hwc_layer_1; struct hwc_procs; struct framebuffer_device_t; @@ -43,6 +44,7 @@ namespace android { // --------------------------------------------------------------------------- class GraphicBuffer; +class Fence; class LayerBase; class Region; class String8; @@ -97,12 +99,18 @@ public: // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED. status_t createWorkList(int32_t id, size_t numLayers); + bool supportsFramebufferTarget() const; + // does this display have layers handled by HWC bool hasHwcComposition(int32_t id) const; // does this display have layers handled by GLES bool hasGlesComposition(int32_t id) const; + // get the releaseFence file descriptor for the given display + // the release fence is only valid after commit() + int getAndResetReleaseFenceFd(int32_t id); + // needed forward declarations class LayerListIterator; @@ -111,7 +119,7 @@ public: int getVisualID() const; // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface). - int fbPost(buffer_handle_t buffer); + int fbPost(int32_t id, const sp& acquireFence, const sp& buf); int fbCompositionComplete(); void fbDump(String8& result); @@ -253,7 +261,6 @@ private: void loadFbHalModule(); LayerListIterator getLayerIterator(int32_t id, size_t index); - size_t getNumLayers(int32_t id) const; struct cb_context; @@ -269,10 +276,15 @@ private: void queryDisplayProperties(int disp); + status_t setFramebufferTarget(int32_t id, + const sp& acquireFence, const sp& buf); + + struct DisplayData { DisplayData() : xdpi(0), ydpi(0), refresh(0), hasFbComp(false), hasOvComp(false), - capacity(0), list(NULL) { } + capacity(0), list(NULL), + framebufferTarget(NULL), fbTargetHandle(NULL) { } ~DisplayData() { free(list); } @@ -286,6 +298,8 @@ private: bool hasOvComp; size_t capacity; hwc_display_contents_1* list; + hwc_layer_1* framebufferTarget; + buffer_handle_t fbTargetHandle; }; sp mFlinger; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6785ba80d..569f6bbc6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -523,6 +523,10 @@ void Layer::onPostComposition() { } } +bool Layer::isVisible() const { + return LayerBaseClient::isVisible() && (mActiveBuffer != NULL); +} + Region Layer::latchBuffer(bool& recomputeVisibleRegions) { ATRACE_CALL(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b839f8c1e..6f75d8c1c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -82,6 +82,7 @@ public: virtual void onRemoved(); virtual sp getLayer() const { return const_cast(this); } virtual void setName(const String8& name); + virtual bool isVisible() const; // LayerBaseClient interface virtual wp getSurfaceTextureBinder() const; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index b61770c5f..99cb8f3cb 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -321,6 +321,11 @@ bool LayerBase::getFiltering() const return mFiltering; } +bool LayerBase::isVisible() const { + const Layer::State& s(mDrawingState); + return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; +} + void LayerBase::draw(const sp& hw, const Region& clip) const { onDraw(hw, clip); diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 7326f533b..99949946c 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -211,6 +211,11 @@ public: */ virtual bool isProtected() const { return false; } + /* + * isVisible - true if this layer is visibile, false otherwise + */ + virtual bool isVisible() const; + /** called with the state lock when the surface is removed from the * current list */ virtual void onRemoved() { } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f62f07598..bdd8c6717 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -245,15 +245,6 @@ status_t SurfaceFlinger::selectConfigForPixelFormat( EGLConfig* const configs = new EGLConfig[numConfigs]; eglChooseConfig(dpy, attrs, configs, numConfigs, &n); - if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { - // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED - // is supported by the implementation. we can only be in this case - // if we have HWC 1.1 - *outConfig = configs[0]; - delete [] configs; - return NO_ERROR; - } - for (int i=0 ; icompositionComplete(); - // FIXME - if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { - eglSwapBuffers(mEGLDisplay, hw->getEGLSurface()); - } + hw->swapBuffers(getHwComposer()); } } } @@ -885,6 +877,7 @@ void SurfaceFlinger::postFramebuffer() for (size_t dpy=0 ; dpy hw(mDisplays[dpy]); const Vector< sp >& currentLayers(hw->getVisibleLayersSortedByZ()); + hw->onSwapBuffersCompleted(hwc); const size_t count = currentLayers.size(); int32_t id = hw->getHwcDisplayId(); if (id >=0 && hwc.initCheck() == NO_ERROR) { @@ -1160,7 +1153,7 @@ void SurfaceFlinger::computeVisibleRegions( // handle hidden surfaces by setting the visible region to empty - if (CC_LIKELY(!(s.flags & layer_state_t::eLayerHidden) && s.alpha)) { + if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(); Rect bounds(layer->computeBounds()); visibleRegion.set(bounds); @@ -1308,20 +1301,11 @@ void SurfaceFlinger::doDisplayComposition(const sp& hw, doComposeSurfaces(hw, dirtyRegion); - // 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 (if there is a hwc) and never for the other ones - if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL || - getHwComposer().initCheck() != NO_ERROR) { - // FIXME: EGL spec says: - // "surface must be bound to the calling thread's current context, - // for the current rendering API." - eglSwapBuffers(mEGLDisplay, hw->getEGLSurface()); - } - // update the swap region and clear the dirty region hw->swapRegion.orSelf(dirtyRegion); + + // swap buffers (presentation) + hw->swapBuffers(getHwComposer()); } void SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty) @@ -1388,6 +1372,12 @@ void SurfaceFlinger::doComposeSurfaces(const sp& hw, const layer->draw(hw, clip); break; } + case HWC_FRAMEBUFFER_TARGET: { + // this should not happen as the iterator shouldn't + // let us get there. + ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%d)", i); + break; + } } } layer->setAcquireFence(hw, *cur);