am d0ffef4b: am 19b23afa: Merge "Fix for phone app crash in Icc Card."
* commit 'd0ffef4b43594e540cb867da18d4403b4f583622':
Fix for phone app crash in Icc Card.
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index a3e85a9..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 @@
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 @@
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); }
@@ -88,12 +98,15 @@
status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
status_t lock(GGLSurface* surface, uint32_t usage);
status_t unlock();
-
+
android_native_buffer_t* getNativeBuffer() const;
void setIndex(int index);
int getIndex() const;
+ // for debugging
+ static void dumpAllocationsToSystemLog();
+
private:
virtual ~GraphicBuffer();
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 54b8236..dffa788 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -68,6 +68,7 @@
status_t free(buffer_handle_t handle);
void dump(String8& res) const;
+ static void dumpToSystemLog();
private:
struct alloc_rec_t {
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 @@
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 519c277..3671954 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -45,6 +45,7 @@
stride =
format =
usage = 0;
+ transform = 0;
handle = NULL;
}
@@ -57,7 +58,8 @@
height =
stride =
format =
- usage = 0;
+ usage =
+ transform = 0;
handle = NULL;
mInitCheck = initSize(w, h, reqFormat, reqUsage);
}
@@ -74,6 +76,7 @@
stride = inStride;
format = inFormat;
usage = inUsage;
+ transform = 0;
handle = inHandle;
}
@@ -99,6 +102,11 @@
return mInitCheck;
}
+void GraphicBuffer::dumpAllocationsToSystemLog()
+{
+ GraphicBufferAllocator::dumpToSystemLog();
+}
+
android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
{
return static_cast<android_native_buffer_t*>(
@@ -177,8 +185,10 @@
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 {
@@ -203,13 +213,14 @@
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;
@@ -218,7 +229,7 @@
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;
@@ -226,7 +237,7 @@
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;
@@ -243,9 +254,10 @@
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/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d51664d..fa46ab7 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -73,6 +73,13 @@
result.append(buffer);
}
+void GraphicBufferAllocator::dumpToSystemLog()
+{
+ String8 s;
+ GraphicBufferAllocator::getInstance().dump(s);
+ LOGD("%s", s.string());
+}
+
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
int usage, buffer_handle_t* handle, int32_t* stride)
{
@@ -104,10 +111,6 @@
rec.usage = usage;
rec.size = h * stride[0] * bytesPerPixel(format);
list.add(*handle, rec);
- } else {
- String8 s;
- dump(s);
- LOGD("%s", s.string());
}
return err;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index ab260d5..ebe2193 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -40,6 +40,8 @@
#include <utils/KeyedVector.h>
#include <utils/String8.h>
+#include <ui/egl/android_natives.h>
+
#include "hooks.h"
#include "egl_impl.h"
#include "Loader.h"
@@ -196,15 +198,16 @@
{
typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
- egl_surface_t(EGLDisplay dpy, EGLSurface surface, EGLConfig config,
- int impl, egl_connection_t const* cnx)
- : dpy(dpy), surface(surface), config(config), impl(impl), cnx(cnx) {
+ egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
+ EGLSurface surface, int impl, egl_connection_t const* cnx)
+ : dpy(dpy), surface(surface), config(config), win(win), impl(impl), cnx(cnx) {
}
~egl_surface_t() {
}
EGLDisplay dpy;
EGLSurface surface;
EGLConfig config;
+ sp<ANativeWindow> win;
int impl;
egl_connection_t const* cnx;
};
@@ -215,8 +218,8 @@
egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
int impl, egl_connection_t const* cnx, int version)
- : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
- version(version)
+ : dpy(dpy), context(context), config(config), read(0), draw(0), impl(impl),
+ cnx(cnx), version(version)
{
}
EGLDisplay dpy;
@@ -984,11 +987,22 @@
egl_display_t const* dp = 0;
egl_connection_t* cnx = validate_display_config(dpy, config, dp);
if (cnx) {
+ EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
+ EGLConfig iConfig = dp->configs[intptr_t(config)].config;
+ EGLint format;
+
+ // set the native window's buffers format to match this config
+ if (cnx->egl.eglGetConfigAttrib(iDpy,
+ iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
+ if (format != 0) {
+ native_window_set_buffers_geometry(window, 0, 0, format);
+ }
+ }
+
EGLSurface surface = cnx->egl.eglCreateWindowSurface(
- dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
- dp->configs[intptr_t(config)].config, window, attrib_list);
+ iDpy, iConfig, window, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dpy, surface, config,
+ egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
dp->configs[intptr_t(config)].impl, cnx);
return s;
}
@@ -1007,7 +1021,7 @@
dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
dp->configs[intptr_t(config)].config, pixmap, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dpy, surface, config,
+ egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
dp->configs[intptr_t(config)].impl, cnx);
return s;
}
@@ -1025,7 +1039,7 @@
dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
dp->configs[intptr_t(config)].config, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dpy, surface, config,
+ egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
dp->configs[intptr_t(config)].impl, cnx);
return s;
}
@@ -1046,6 +1060,9 @@
EGLBoolean result = s->cnx->egl.eglDestroySurface(
dp->disp[s->impl].dpy, s->surface);
if (result == EGL_TRUE) {
+ if (s->win != NULL) {
+ native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
+ }
_s.terminate();
}
return result;
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 @@
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 @@
//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 @@
// 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 a060d31..3a8690e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -57,7 +57,8 @@
mSecure(false),
mTextureManager(),
mBufferManager(mTextureManager),
- mWidth(0), mHeight(0), mFixedSize(false)
+ mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false),
+ mBypassState(false)
{
}
@@ -216,13 +217,10 @@
void Layer::drawForSreenShot() const
{
- bool currentFixedSize = mFixedSize;
- bool currentBlending = mNeedsBlending;
- const_cast<Layer*>(this)->mFixedSize = false;
- const_cast<Layer*>(this)->mFixedSize = true;
+ const bool currentFiltering = mNeedsFiltering;
+ const_cast<Layer*>(this)->mNeedsFiltering = true;
LayerBase::drawForSreenShot();
- const_cast<Layer*>(this)->mFixedSize = currentFixedSize;
- const_cast<Layer*>(this)->mNeedsBlending = currentBlending;
+ const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering;
}
void Layer::onDraw(const Region& clip) const
@@ -254,17 +252,39 @@
}
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);
}
bool Layer::needsFiltering() const
{
if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
- // NOTE: there is a race here, because mFixedSize is updated in a
- // binder transaction. however, it doesn't really matter since it is
- // evaluated each time we draw. To be perfectly correct, this flag
- // would have to be associated with a buffer.
- if (mFixedSize)
+ // if our buffer is not the same size than ourselves,
+ // we need filtering.
+ Mutex::Autolock _l(mLock);
+ if (mNeedsScaling)
return true;
}
return LayerBase::needsFiltering();
@@ -315,12 +335,14 @@
* 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;
if (!reqWidth) reqWidth = mWidth;
if (!reqHeight) reqHeight = mHeight;
@@ -334,6 +356,7 @@
mReqWidth = reqWidth;
mReqHeight = reqHeight;
mReqFormat = reqFormat;
+ mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
lcblk->reallocateAllExcept(index);
}
@@ -342,11 +365,43 @@
// 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();
LOGE_IF(err || buffer->handle == 0,
"Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
this, index, w, h, strerror(-err));
@@ -390,6 +445,39 @@
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;
+}
+
+void Layer::updateBuffersOrientation()
+{
+ sp<GraphicBuffer> buffer(getBypassBuffer());
+ if (buffer != NULL && mOrientation != buffer->transform) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) { // all buffers need reallocation
+ lcblk->reallocateAll();
+ }
+ }
+}
+
uint32_t Layer::doTransaction(uint32_t flags)
{
const Layer::State& front(drawingState());
@@ -456,6 +544,7 @@
Mutex::Autolock _l(mLock);
mWidth = w;
mHeight = h;
+ mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
}
bool Layer::isFixedSize() const {
@@ -639,9 +728,9 @@
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 263c372..cb62558 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -81,6 +81,12 @@
virtual sp<Surface> createSurface() const;
virtual status_t ditch();
virtual void onRemoved();
+ virtual bool setBypass(bool enable);
+
+ void updateBuffersOrientation();
+
+ inline sp<GraphicBuffer> getBypassBuffer() const {
+ return mBufferManager.getActiveBuffer(); }
// only for debugging
inline sp<GraphicBuffer> getBuffer(int i) const {
@@ -230,7 +236,9 @@
uint32_t mReqWidth;
uint32_t mReqHeight;
uint32_t mReqFormat;
+ bool mNeedsScaling;
bool mFixedSize;
+ bool mBypassState;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 64eed4b..79c6d0d 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -216,14 +216,10 @@
flags |= eVisibleRegion;
this->contentDirty = true;
- mNeedsFiltering = false;
- if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
- // we may use linear filtering, if the matrix scales us
- const uint8_t type = temp.transform.getType();
- if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
- mNeedsFiltering = true;
- }
- }
+ // we may use linear filtering, if the matrix scales us
+ const uint8_t type = temp.transform.getType();
+ mNeedsFiltering = (!temp.transform.preserveRects() ||
+ (type >= Transform::SCALE));
}
// Commit the transaction
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d688f65..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 @@
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;
@@ -185,7 +191,9 @@
/**
* needsLinearFiltering - true if this surface needs filtering
*/
- virtual bool needsFiltering() const { return mNeedsFiltering; }
+ virtual bool needsFiltering() const {
+ return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
+ }
/**
* isSecure - true if this surface is secure, that is if it prevents
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a9b3965..af0f95a 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 @@
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 @@
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,32 @@
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) {
+ if (cur != NULL) {
+ cur->updateBuffersOrientation();
+ }
+ 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 +772,21 @@
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 +1482,9 @@
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 @@
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 @@
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 @@
int32_t mFreezeCount;
nsecs_t mFreezeDisplayTime;
Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
+ wp<Layer> mBypassLayer;
// don't use a lock for these, we don't care