summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2010-12-07 14:22:56 -0800
committerAndroid Git Automerger <android-git-automerger@android.com>2010-12-07 14:22:56 -0800
commit4e345ab7df737592528e99db73612c6b37e34545 (patch)
tree8eded6da95e3c0929209c992c7f0c5db9778508e /services/surfaceflinger
parenta0f011ff499289c89535c41ebe79c8c642414dff (diff)
parenta2977c383d363e1e88a5b36230b1fa4c312807d2 (diff)
downloadframeworks_base-4e345ab7df737592528e99db73612c6b37e34545.zip
frameworks_base-4e345ab7df737592528e99db73612c6b37e34545.tar.gz
frameworks_base-4e345ab7df737592528e99db73612c6b37e34545.tar.bz2
am a2977c38: Merge changes Ie03796ae,Ide3e980a into gingerbread
* commit 'a2977c383d363e1e88a5b36230b1fa4c312807d2': [3171580] SurfaceFlinger Bypass mode. (DO NOT MERGE) [3171580] Add transform field to native buffers. (DO NOT MERGE)
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/Android.mk1
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp6
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.h1
-rw-r--r--services/surfaceflinger/Layer.cpp93
-rw-r--r--services/surfaceflinger/Layer.h5
-rw-r--r--services/surfaceflinger/LayerBase.h6
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp68
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h3
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