diff options
-rw-r--r-- | include/ui/GraphicBuffer.h | 10 | ||||
-rw-r--r-- | include/ui/android_native_buffer.h | 8 | ||||
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 19 | ||||
-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 |
11 files changed, 201 insertions, 19 deletions
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index 6edc3ca..0be26a7 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -26,6 +26,8 @@ #include <utils/Flattenable.h> #include <pixelflinger/pixelflinger.h> +#include <hardware/hardware.h> + struct android_native_buffer_t; namespace android { @@ -63,6 +65,13 @@ public: USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK }; + enum { + TRANSFORM_IDENTITY = 0, + TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90, + TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180, + TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270 + }; + GraphicBuffer(); // creates w * h buffer @@ -79,6 +88,7 @@ public: uint32_t getHeight() const { return height; } uint32_t getStride() const { return stride; } uint32_t getUsage() const { return usage; } + uint32_t getTransform() const { return transform; } PixelFormat getPixelFormat() const { return format; } Rect getBounds() const { return Rect(width, height); } diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h index 402843e..a472824 100644 --- a/include/ui/android_native_buffer.h +++ b/include/ui/android_native_buffer.h @@ -51,8 +51,12 @@ typedef struct android_native_buffer_t int stride; int format; int usage; - - void* reserved[2]; + + /* transformation as defined in hardware.h */ + uint8_t transform; + + uint8_t reserved_bytes[3]; + void* reserved[1]; buffer_handle_t handle; diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 828a988..3671954 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -45,6 +45,7 @@ GraphicBuffer::GraphicBuffer() stride = format = usage = 0; + transform = 0; handle = NULL; } @@ -57,7 +58,8 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, height = stride = format = - usage = 0; + usage = + transform = 0; handle = NULL; mInitCheck = initSize(w, h, reqFormat, reqUsage); } @@ -74,6 +76,7 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, stride = inStride; format = inFormat; usage = inUsage; + transform = 0; handle = inHandle; } @@ -182,8 +185,10 @@ status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage) return res; } +const int kFlattenFdsOffset = 9; + size_t GraphicBuffer::getFlattenedSize() const { - return (8 + (handle ? handle->numInts : 0))*sizeof(int); + return (kFlattenFdsOffset + (handle ? handle->numInts : 0))*sizeof(int); } size_t GraphicBuffer::getFdCount() const { @@ -208,13 +213,14 @@ status_t GraphicBuffer::flatten(void* buffer, size_t size, buf[5] = usage; buf[6] = 0; buf[7] = 0; + buf[8] = transform; if (handle) { buf[6] = handle->numFds; buf[7] = handle->numInts; native_handle_t const* const h = handle; memcpy(fds, h->data, h->numFds*sizeof(int)); - memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int)); + memcpy(&buf[kFlattenFdsOffset], h->data + h->numFds, h->numInts*sizeof(int)); } return NO_ERROR; @@ -223,7 +229,7 @@ status_t GraphicBuffer::flatten(void* buffer, size_t size, status_t GraphicBuffer::unflatten(void const* buffer, size_t size, int fds[], size_t count) { - if (size < 8*sizeof(int)) return NO_MEMORY; + if (size < kFlattenFdsOffset*sizeof(int)) return NO_MEMORY; int const* buf = static_cast<int const*>(buffer); if (buf[0] != 'GBFR') return BAD_TYPE; @@ -231,7 +237,7 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size, const size_t numFds = buf[6]; const size_t numInts = buf[7]; - const size_t sizeNeeded = (8 + numInts) * sizeof(int); + const size_t sizeNeeded = (kFlattenFdsOffset + numInts) * sizeof(int); if (size < sizeNeeded) return NO_MEMORY; size_t fdCountNeeded = 0; @@ -248,9 +254,10 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size, stride = buf[3]; format = buf[4]; usage = buf[5]; + transform = buf[8]; native_handle* h = native_handle_create(numFds, numInts); memcpy(h->data, fds, numFds*sizeof(int)); - memcpy(h->data + numFds, &buf[8], numInts*sizeof(int)); + memcpy(h->data + numFds, &buf[kFlattenFdsOffset], numInts*sizeof(int)); handle = h; } else { width = height = stride = format = usage = 0; 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 |