diff options
author | Mathias Agopian <mathias@google.com> | 2010-11-01 23:32:18 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2010-12-03 17:35:07 -0800 |
commit | 025005f562f695c3b1785745c2e5c184fc3a2330 (patch) | |
tree | 850177ccb405a2234b885b41624c0253b02db128 /services | |
parent | 48e723a0ee9b625825d23642f843b91fa276ab7c (diff) | |
download | frameworks_base-025005f562f695c3b1785745c2e5c184fc3a2330.zip frameworks_base-025005f562f695c3b1785745c2e5c184fc3a2330.tar.gz frameworks_base-025005f562f695c3b1785745c2e5c184fc3a2330.tar.bz2 |
[3171580] SurfaceFlinger Bypass mode. (DO NOT MERGE)
This is a poor's man precursor to the h/w composer HAL.
Basically we detect when a window is full screen and in
that case we bypass surfaceflinger's composition step, which
yields to much improved performance.
Change-Id: Ie03796ae81a1c951949b771c9323044b980cb347
Diffstat (limited to 'services')
-rw-r--r-- | services/surfaceflinger/Android.mk | 1 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 93 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 68 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 3 |
8 files changed, 172 insertions, 11 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index e2f8a74..41562f6 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -25,6 +25,7 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3) endif ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY + LOCAL_CFLAGS += -DUSE_COMPOSITION_BYPASS endif diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 28a512e..818774d 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -339,6 +339,12 @@ void DisplayHardware::flip(const Region& dirty) const //glClear(GL_COLOR_BUFFER_BIT); } +status_t DisplayHardware::postBypassBuffer(const native_handle_t* handle) const +{ + framebuffer_device_t *fbDev = (framebuffer_device_t *)mNativeWindow->getDevice(); + return fbDev->post(fbDev, handle); +} + uint32_t DisplayHardware::getFlags() const { return mFlags; diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index 2d7900c..79ef2a7 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -64,6 +64,7 @@ public: // Flip the front and back buffers if the back buffer is "dirty". Might // be instantaneous, might involve copying the frame buffer around. void flip(const Region& dirty) const; + status_t postBypassBuffer(const native_handle_t* handle) const; float getDpiX() const; float getDpiY() const; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 81cb15d..a18f473 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -57,7 +57,8 @@ Layer::Layer(SurfaceFlinger* flinger, mSecure(false), mTextureManager(), mBufferManager(mTextureManager), - mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false) + mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false), + mBypassState(false) { } @@ -251,6 +252,29 @@ void Layer::onDraw(const Region& clip) const } return; } + +#ifdef USE_COMPOSITION_BYPASS + sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer()); + if ((buffer != NULL) && (buffer->transform)) { + // Here we have a "bypass" buffer, but we need to composite it + // most likely because it's not fullscreen anymore. + // Since the buffer may have a transformation applied by the client + // we need to inverse this transformation here. + + // calculate the inverse of the buffer transform + const uint32_t mask = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H; + const uint32_t bufferTransformInverse = buffer->transform ^ mask; + + // To accomplish the inverse transform, we use "mBufferTransform" + // which is not used by Layer.cpp + const_cast<Layer*>(this)->mBufferTransform = bufferTransformInverse; + drawWithOpenGL(clip, tex); + // reset to "no transfrom" + const_cast<Layer*>(this)->mBufferTransform = 0; + return; + } +#endif + drawWithOpenGL(clip, tex); } @@ -311,11 +335,12 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, * buffer 'index' as our front buffer. */ - status_t err = NO_ERROR; - uint32_t w, h, f; + uint32_t w, h, f, bypass; { // scope for the lock Mutex::Autolock _l(mLock); + bypass = mBypassState; + // zero means default mFixedSize = reqWidth && reqHeight; if (!reqFormat) reqFormat = mFormat; @@ -340,9 +365,40 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, // here we have to reallocate a new buffer because the buffer could be // used as the front buffer, or by a client in our process // (eg: status bar), and we can't release the handle under its feet. - const uint32_t effectiveUsage = getEffectiveUsage(usage); - buffer = new GraphicBuffer(w, h, f, effectiveUsage); - err = buffer->initCheck(); + uint32_t effectiveUsage = getEffectiveUsage(usage); + + status_t err = NO_MEMORY; + +#ifdef USE_COMPOSITION_BYPASS + if (!mSecure && bypass && (effectiveUsage & GRALLOC_USAGE_HW_RENDER)) { + // always allocate a buffer matching the screen size. the size + // may be different from (w,h) if the buffer is rotated. + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + int32_t w = hw.getWidth(); + int32_t h = hw.getHeight(); + int32_t f = hw.getFormat(); + + buffer = new GraphicBuffer(w, h, f, effectiveUsage | GRALLOC_USAGE_HW_FB); + err = buffer->initCheck(); + buffer->transform = uint8_t(getOrientation()); + + if (err != NO_ERROR) { + // allocation didn't succeed, probably because an older bypass + // window hasn't released all its resources yet. + ClientRef::Access sharedClient(mUserClientRef); + SharedBufferServer* lcblk(sharedClient.get()); + if (lcblk) { + // all buffers need reallocation + lcblk->reallocateAll(); + } + } + } +#endif + + if (err != NO_ERROR) { + buffer = new GraphicBuffer(w, h, f, effectiveUsage); + err = buffer->initCheck(); + } if (err || buffer->handle == 0) { GraphicBuffer::dumpAllocationsToSystemLog(); @@ -389,6 +445,27 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const return usage; } +bool Layer::setBypass(bool enable) +{ + Mutex::Autolock _l(mLock); + + if (mNeedsScaling || mNeedsFiltering) { + return false; + } + + if (mBypassState != enable) { + mBypassState = enable; + ClientRef::Access sharedClient(mUserClientRef); + SharedBufferServer* lcblk(sharedClient.get()); + if (lcblk) { + // all buffers need reallocation + lcblk->reallocateAll(); + } + } + + return true; +} + uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); @@ -639,9 +716,9 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const snprintf(buffer, SIZE, " " "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," - " freezeLock=%p, dq-q-time=%u us\n", + " freezeLock=%p, bypass=%d, dq-q-time=%u us\n", mFormat, w0, h0, s0, w1, h1, s1, - getFreezeLock().get(), totalTime); + getFreezeLock().get(), mBypassState, totalTime); result.append(buffer); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index a93fcb1..9ff5716 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -81,6 +81,10 @@ public: virtual sp<Surface> createSurface() const; virtual status_t ditch(); virtual void onRemoved(); + virtual bool setBypass(bool enable); + + inline sp<GraphicBuffer> getBypassBuffer() const { + return mBufferManager.getActiveBuffer(); } // only for debugging inline sp<GraphicBuffer> getBuffer(int i) const { @@ -232,6 +236,7 @@ private: uint32_t mReqFormat; bool mNeedsScaling; bool mFixedSize; + bool mBypassState; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 633df96..3ec8ac3 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -35,6 +35,7 @@ #include <pixelflinger/pixelflinger.h> +#include "DisplayHardware/DisplayHardware.h" #include "Transform.h" namespace android { @@ -118,6 +119,11 @@ public: virtual void drawForSreenShot() const; /** + * bypass mode + */ + virtual bool setBypass(bool enable) { return false; } + + /** * onDraw - draws the surface. */ virtual void onDraw(const Region& clip) const = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a9b3965..5e9e06c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -61,6 +61,10 @@ #define AID_GRAPHICS 1003 #endif +#ifdef USE_COMPOSITION_BYPASS +#warning "using COMPOSITION_BYPASS" +#endif + #define DISPLAY_COUNT 1 namespace android { @@ -373,8 +377,15 @@ bool SurfaceFlinger::threadLoop() const DisplayHardware& hw(graphicPlane(0).displayHardware()); if (LIKELY(hw.canDraw() && !isFrozen())) { - // repaint the framebuffer (if needed) +#ifdef USE_COMPOSITION_BYPASS + if (handleBypassLayer()) { + unlockClients(); + return true; + } +#endif + + // repaint the framebuffer (if needed) const int index = hw.getCurrentBufferIndex(); GraphicLog& logger(GraphicLog::getInstance()); @@ -401,6 +412,20 @@ bool SurfaceFlinger::threadLoop() return true; } +bool SurfaceFlinger::handleBypassLayer() +{ + sp<Layer> bypassLayer(mBypassLayer.promote()); + if (bypassLayer != 0) { + sp<GraphicBuffer> buffer(bypassLayer->getBypassBuffer()); + if (buffer!=0 && (buffer->usage & GRALLOC_USAGE_HW_FB)) { + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.postBypassBuffer(buffer->handle); + return true; + } + } + return false; +} + void SurfaceFlinger::postFramebuffer() { if (!mInvalidRegion.isEmpty()) { @@ -696,6 +721,28 @@ void SurfaceFlinger::commitTransaction() mTransactionCV.broadcast(); } +void SurfaceFlinger::setBypassLayer(const sp<LayerBase>& layer) +{ + // if this layer is already the bypass layer, do nothing + sp<Layer> cur(mBypassLayer.promote()); + if (mBypassLayer == layer) + return; + + // clear the current bypass layer + mBypassLayer.clear(); + if (cur != 0) { + cur->setBypass(false); + cur.clear(); + } + + // set new bypass layer + if (layer != 0) { + if (layer->setBypass(true)) { + mBypassLayer = static_cast<Layer*>(layer.get()); + } + } +} + void SurfaceFlinger::handlePageFlip() { bool visibleRegions = mVisibleRegionsDirty; @@ -721,6 +768,21 @@ void SurfaceFlinger::handlePageFlip() mVisibleLayersSortedByZ.add(currentLayers[i]); } +#ifdef USE_COMPOSITION_BYPASS + sp<LayerBase> bypassLayer; + const size_t numVisibleLayers = mVisibleLayersSortedByZ.size(); + if (numVisibleLayers == 1) { + const sp<LayerBase>& candidate(mVisibleLayersSortedByZ[0]); + const Region& visibleRegion(candidate->visibleRegionScreen); + const Region reminder(screenRegion.subtract(visibleRegion)); + if (reminder.isEmpty()) { + // fullscreen candidate! + bypassLayer = candidate; + } + } + setBypassLayer(bypassLayer); +#endif + mWormholeRegion = screenRegion.subtract(opaqueRegion); mVisibleRegionsDirty = false; } @@ -1416,9 +1478,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) mWormholeRegion.dump(result, "WormholeRegion"); const DisplayHardware& hw(graphicPlane(0).displayHardware()); snprintf(buffer, SIZE, - " display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n", + " display frozen: %s, freezeCount=%d, orientation=%d, bypass=%p, canDraw=%d\n", mFreezeDisplay?"yes":"no", mFreezeCount, - mCurrentState.orientation, hw.canDraw()); + mCurrentState.orientation, mBypassLayer.unsafe_get(), hw.canDraw()); result.append(buffer); snprintf(buffer, SIZE, " last eglSwapBuffers() time: %f us\n" diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 4262175..ca57292 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -307,6 +307,7 @@ private: bool lockPageFlip(const LayerVector& currentLayers); void unlockPageFlip(const LayerVector& currentLayers); void handleRepaint(); + bool handleBypassLayer(); void postFramebuffer(); void composeSurfaces(const Region& dirty); void unlockClients(); @@ -322,6 +323,7 @@ private: uint32_t setTransactionFlags(uint32_t flags); void commitTransaction(); + void setBypassLayer(const sp<LayerBase>& layer); status_t captureScreenImplLocked(DisplayID dpy, sp<IMemoryHeap>* heap, @@ -399,6 +401,7 @@ private: int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; Vector< sp<LayerBase> > mVisibleLayersSortedByZ; + wp<Layer> mBypassLayer; // don't use a lock for these, we don't care |