Skip to content

Commit 025005f

Browse files
committed
[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
1 parent 48e723a commit 025005f

File tree

8 files changed

+172
-11
lines changed

8 files changed

+172
-11
lines changed

services/surfaceflinger/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3)
2525
endif
2626
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
2727
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
28+
LOCAL_CFLAGS += -DUSE_COMPOSITION_BYPASS
2829
endif
2930

3031

services/surfaceflinger/DisplayHardware/DisplayHardware.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,12 @@ void DisplayHardware::flip(const Region& dirty) const
339339
//glClear(GL_COLOR_BUFFER_BIT);
340340
}
341341

342+
status_t DisplayHardware::postBypassBuffer(const native_handle_t* handle) const
343+
{
344+
framebuffer_device_t *fbDev = (framebuffer_device_t *)mNativeWindow->getDevice();
345+
return fbDev->post(fbDev, handle);
346+
}
347+
342348
uint32_t DisplayHardware::getFlags() const
343349
{
344350
return mFlags;

services/surfaceflinger/DisplayHardware/DisplayHardware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class DisplayHardware : public DisplayHardwareBase
6464
// Flip the front and back buffers if the back buffer is "dirty". Might
6565
// be instantaneous, might involve copying the frame buffer around.
6666
void flip(const Region& dirty) const;
67+
status_t postBypassBuffer(const native_handle_t* handle) const;
6768

6869
float getDpiX() const;
6970
float getDpiY() const;

services/surfaceflinger/Layer.cpp

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ Layer::Layer(SurfaceFlinger* flinger,
5757
mSecure(false),
5858
mTextureManager(),
5959
mBufferManager(mTextureManager),
60-
mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false)
60+
mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false),
61+
mBypassState(false)
6162
{
6263
}
6364

@@ -251,6 +252,29 @@ void Layer::onDraw(const Region& clip) const
251252
}
252253
return;
253254
}
255+
256+
#ifdef USE_COMPOSITION_BYPASS
257+
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
258+
if ((buffer != NULL) && (buffer->transform)) {
259+
// Here we have a "bypass" buffer, but we need to composite it
260+
// most likely because it's not fullscreen anymore.
261+
// Since the buffer may have a transformation applied by the client
262+
// we need to inverse this transformation here.
263+
264+
// calculate the inverse of the buffer transform
265+
const uint32_t mask = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
266+
const uint32_t bufferTransformInverse = buffer->transform ^ mask;
267+
268+
// To accomplish the inverse transform, we use "mBufferTransform"
269+
// which is not used by Layer.cpp
270+
const_cast<Layer*>(this)->mBufferTransform = bufferTransformInverse;
271+
drawWithOpenGL(clip, tex);
272+
// reset to "no transfrom"
273+
const_cast<Layer*>(this)->mBufferTransform = 0;
274+
return;
275+
}
276+
#endif
277+
254278
drawWithOpenGL(clip, tex);
255279
}
256280

@@ -311,11 +335,12 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
311335
* buffer 'index' as our front buffer.
312336
*/
313337

314-
status_t err = NO_ERROR;
315-
uint32_t w, h, f;
338+
uint32_t w, h, f, bypass;
316339
{ // scope for the lock
317340
Mutex::Autolock _l(mLock);
318341

342+
bypass = mBypassState;
343+
319344
// zero means default
320345
mFixedSize = reqWidth && reqHeight;
321346
if (!reqFormat) reqFormat = mFormat;
@@ -340,9 +365,40 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
340365
// here we have to reallocate a new buffer because the buffer could be
341366
// used as the front buffer, or by a client in our process
342367
// (eg: status bar), and we can't release the handle under its feet.
343-
const uint32_t effectiveUsage = getEffectiveUsage(usage);
344-
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
345-
err = buffer->initCheck();
368+
uint32_t effectiveUsage = getEffectiveUsage(usage);
369+
370+
status_t err = NO_MEMORY;
371+
372+
#ifdef USE_COMPOSITION_BYPASS
373+
if (!mSecure && bypass && (effectiveUsage & GRALLOC_USAGE_HW_RENDER)) {
374+
// always allocate a buffer matching the screen size. the size
375+
// may be different from (w,h) if the buffer is rotated.
376+
const DisplayHardware& hw(graphicPlane(0).displayHardware());
377+
int32_t w = hw.getWidth();
378+
int32_t h = hw.getHeight();
379+
int32_t f = hw.getFormat();
380+
381+
buffer = new GraphicBuffer(w, h, f, effectiveUsage | GRALLOC_USAGE_HW_FB);
382+
err = buffer->initCheck();
383+
buffer->transform = uint8_t(getOrientation());
384+
385+
if (err != NO_ERROR) {
386+
// allocation didn't succeed, probably because an older bypass
387+
// window hasn't released all its resources yet.
388+
ClientRef::Access sharedClient(mUserClientRef);
389+
SharedBufferServer* lcblk(sharedClient.get());
390+
if (lcblk) {
391+
// all buffers need reallocation
392+
lcblk->reallocateAll();
393+
}
394+
}
395+
}
396+
#endif
397+
398+
if (err != NO_ERROR) {
399+
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
400+
err = buffer->initCheck();
401+
}
346402

347403
if (err || buffer->handle == 0) {
348404
GraphicBuffer::dumpAllocationsToSystemLog();
@@ -389,6 +445,27 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
389445
return usage;
390446
}
391447

448+
bool Layer::setBypass(bool enable)
449+
{
450+
Mutex::Autolock _l(mLock);
451+
452+
if (mNeedsScaling || mNeedsFiltering) {
453+
return false;
454+
}
455+
456+
if (mBypassState != enable) {
457+
mBypassState = enable;
458+
ClientRef::Access sharedClient(mUserClientRef);
459+
SharedBufferServer* lcblk(sharedClient.get());
460+
if (lcblk) {
461+
// all buffers need reallocation
462+
lcblk->reallocateAll();
463+
}
464+
}
465+
466+
return true;
467+
}
468+
392469
uint32_t Layer::doTransaction(uint32_t flags)
393470
{
394471
const Layer::State& front(drawingState());
@@ -639,9 +716,9 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
639716
snprintf(buffer, SIZE,
640717
" "
641718
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
642-
" freezeLock=%p, dq-q-time=%u us\n",
719+
" freezeLock=%p, bypass=%d, dq-q-time=%u us\n",
643720
mFormat, w0, h0, s0, w1, h1, s1,
644-
getFreezeLock().get(), totalTime);
721+
getFreezeLock().get(), mBypassState, totalTime);
645722

646723
result.append(buffer);
647724
}

services/surfaceflinger/Layer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ class Layer : public LayerBaseClient
8181
virtual sp<Surface> createSurface() const;
8282
virtual status_t ditch();
8383
virtual void onRemoved();
84+
virtual bool setBypass(bool enable);
85+
86+
inline sp<GraphicBuffer> getBypassBuffer() const {
87+
return mBufferManager.getActiveBuffer(); }
8488

8589
// only for debugging
8690
inline sp<GraphicBuffer> getBuffer(int i) const {
@@ -232,6 +236,7 @@ class Layer : public LayerBaseClient
232236
uint32_t mReqFormat;
233237
bool mNeedsScaling;
234238
bool mFixedSize;
239+
bool mBypassState;
235240
};
236241

237242
// ---------------------------------------------------------------------------

services/surfaceflinger/LayerBase.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#include <pixelflinger/pixelflinger.h>
3737

38+
#include "DisplayHardware/DisplayHardware.h"
3839
#include "Transform.h"
3940

4041
namespace android {
@@ -117,6 +118,11 @@ class LayerBase : public RefBase
117118
virtual void draw(const Region& clip) const;
118119
virtual void drawForSreenShot() const;
119120

121+
/**
122+
* bypass mode
123+
*/
124+
virtual bool setBypass(bool enable) { return false; }
125+
120126
/**
121127
* onDraw - draws the surface.
122128
*/

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
#define AID_GRAPHICS 1003
6262
#endif
6363

64+
#ifdef USE_COMPOSITION_BYPASS
65+
#warning "using COMPOSITION_BYPASS"
66+
#endif
67+
6468
#define DISPLAY_COUNT 1
6569

6670
namespace android {
@@ -373,8 +377,15 @@ bool SurfaceFlinger::threadLoop()
373377

374378
const DisplayHardware& hw(graphicPlane(0).displayHardware());
375379
if (LIKELY(hw.canDraw() && !isFrozen())) {
376-
// repaint the framebuffer (if needed)
377380

381+
#ifdef USE_COMPOSITION_BYPASS
382+
if (handleBypassLayer()) {
383+
unlockClients();
384+
return true;
385+
}
386+
#endif
387+
388+
// repaint the framebuffer (if needed)
378389
const int index = hw.getCurrentBufferIndex();
379390
GraphicLog& logger(GraphicLog::getInstance());
380391

@@ -401,6 +412,20 @@ bool SurfaceFlinger::threadLoop()
401412
return true;
402413
}
403414

415+
bool SurfaceFlinger::handleBypassLayer()
416+
{
417+
sp<Layer> bypassLayer(mBypassLayer.promote());
418+
if (bypassLayer != 0) {
419+
sp<GraphicBuffer> buffer(bypassLayer->getBypassBuffer());
420+
if (buffer!=0 && (buffer->usage & GRALLOC_USAGE_HW_FB)) {
421+
const DisplayHardware& hw(graphicPlane(0).displayHardware());
422+
hw.postBypassBuffer(buffer->handle);
423+
return true;
424+
}
425+
}
426+
return false;
427+
}
428+
404429
void SurfaceFlinger::postFramebuffer()
405430
{
406431
if (!mInvalidRegion.isEmpty()) {
@@ -696,6 +721,28 @@ void SurfaceFlinger::commitTransaction()
696721
mTransactionCV.broadcast();
697722
}
698723

724+
void SurfaceFlinger::setBypassLayer(const sp<LayerBase>& layer)
725+
{
726+
// if this layer is already the bypass layer, do nothing
727+
sp<Layer> cur(mBypassLayer.promote());
728+
if (mBypassLayer == layer)
729+
return;
730+
731+
// clear the current bypass layer
732+
mBypassLayer.clear();
733+
if (cur != 0) {
734+
cur->setBypass(false);
735+
cur.clear();
736+
}
737+
738+
// set new bypass layer
739+
if (layer != 0) {
740+
if (layer->setBypass(true)) {
741+
mBypassLayer = static_cast<Layer*>(layer.get());
742+
}
743+
}
744+
}
745+
699746
void SurfaceFlinger::handlePageFlip()
700747
{
701748
bool visibleRegions = mVisibleRegionsDirty;
@@ -721,6 +768,21 @@ void SurfaceFlinger::handlePageFlip()
721768
mVisibleLayersSortedByZ.add(currentLayers[i]);
722769
}
723770

771+
#ifdef USE_COMPOSITION_BYPASS
772+
sp<LayerBase> bypassLayer;
773+
const size_t numVisibleLayers = mVisibleLayersSortedByZ.size();
774+
if (numVisibleLayers == 1) {
775+
const sp<LayerBase>& candidate(mVisibleLayersSortedByZ[0]);
776+
const Region& visibleRegion(candidate->visibleRegionScreen);
777+
const Region reminder(screenRegion.subtract(visibleRegion));
778+
if (reminder.isEmpty()) {
779+
// fullscreen candidate!
780+
bypassLayer = candidate;
781+
}
782+
}
783+
setBypassLayer(bypassLayer);
784+
#endif
785+
724786
mWormholeRegion = screenRegion.subtract(opaqueRegion);
725787
mVisibleRegionsDirty = false;
726788
}
@@ -1416,9 +1478,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
14161478
mWormholeRegion.dump(result, "WormholeRegion");
14171479
const DisplayHardware& hw(graphicPlane(0).displayHardware());
14181480
snprintf(buffer, SIZE,
1419-
" display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
1481+
" display frozen: %s, freezeCount=%d, orientation=%d, bypass=%p, canDraw=%d\n",
14201482
mFreezeDisplay?"yes":"no", mFreezeCount,
1421-
mCurrentState.orientation, hw.canDraw());
1483+
mCurrentState.orientation, mBypassLayer.unsafe_get(), hw.canDraw());
14221484
result.append(buffer);
14231485
snprintf(buffer, SIZE,
14241486
" last eglSwapBuffers() time: %f us\n"

services/surfaceflinger/SurfaceFlinger.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ class SurfaceFlinger :
307307
bool lockPageFlip(const LayerVector& currentLayers);
308308
void unlockPageFlip(const LayerVector& currentLayers);
309309
void handleRepaint();
310+
bool handleBypassLayer();
310311
void postFramebuffer();
311312
void composeSurfaces(const Region& dirty);
312313
void unlockClients();
@@ -322,6 +323,7 @@ class SurfaceFlinger :
322323
uint32_t setTransactionFlags(uint32_t flags);
323324
void commitTransaction();
324325

326+
void setBypassLayer(const sp<LayerBase>& layer);
325327

326328
status_t captureScreenImplLocked(DisplayID dpy,
327329
sp<IMemoryHeap>* heap,
@@ -399,6 +401,7 @@ class SurfaceFlinger :
399401
int32_t mFreezeCount;
400402
nsecs_t mFreezeDisplayTime;
401403
Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
404+
wp<Layer> mBypassLayer;
402405

403406

404407
// don't use a lock for these, we don't care

0 commit comments

Comments
 (0)