Merge "Fix bug 5045498 Unhide Remote Control Client API"
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 392193b..5ccf87f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -78,12 +78,8 @@
// conditionals don't get stripped... but that is probably what we want.
#if !LOG_NDEBUG
static const char *kReturnStrings[] = {
-#if 1 /* TODO: error update strings */
- "unknown",
-#else
+ "BR_ERROR",
"BR_OK",
- "BR_TIMEOUT",
- "BR_WAKEUP",
"BR_TRANSACTION",
"BR_REPLY",
"BR_ACQUIRE_RESULT",
@@ -94,25 +90,19 @@
"BR_RELEASE",
"BR_DECREFS",
"BR_ATTEMPT_ACQUIRE",
- "BR_EVENT_OCCURRED",
"BR_NOOP",
"BR_SPAWN_LOOPER",
"BR_FINISHED",
"BR_DEAD_BINDER",
- "BR_CLEAR_DEATH_NOTIFICATION_DONE"
-#endif
+ "BR_CLEAR_DEATH_NOTIFICATION_DONE",
+ "BR_FAILED_REPLY"
};
static const char *kCommandStrings[] = {
-#if 1 /* TODO: error update strings */
- "unknown",
-#else
- "BC_NOOP",
"BC_TRANSACTION",
"BC_REPLY",
"BC_ACQUIRE_RESULT",
"BC_FREE_BUFFER",
- "BC_TRANSACTION_COMPLETE",
"BC_INCREFS",
"BC_ACQUIRE",
"BC_RELEASE",
@@ -120,18 +110,12 @@
"BC_INCREFS_DONE",
"BC_ACQUIRE_DONE",
"BC_ATTEMPT_ACQUIRE",
- "BC_RETRIEVE_ROOT_OBJECT",
- "BC_SET_THREAD_ENTRY",
"BC_REGISTER_LOOPER",
"BC_ENTER_LOOPER",
"BC_EXIT_LOOPER",
- "BC_SYNC",
- "BC_STOP_PROCESS",
- "BC_STOP_SELF",
"BC_REQUEST_DEATH_NOTIFICATION",
"BC_CLEAR_DEATH_NOTIFICATION",
"BC_DEAD_BINDER_DONE"
-#endif
};
static const char* getReturnString(size_t idx)
@@ -154,30 +138,36 @@
{
const binder_transaction_data* btd =
(const binder_transaction_data*)data;
- out << "target=" << btd->target.ptr << " (cookie " << btd->cookie << ")" << endl
+ if (btd->target.handle < 1024) {
+ /* want to print descriptors in decimal; guess based on value */
+ out << "target.desc=" << btd->target.handle;
+ } else {
+ out << "target.ptr=" << btd->target.ptr;
+ }
+ out << " (cookie " << btd->cookie << ")" << endl
<< "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl
<< "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
<< " bytes)" << endl
<< "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
- << " bytes)" << endl;
+ << " bytes)";
return btd+1;
}
static const void* printReturnCommand(TextOutput& out, const void* _cmd)
{
- static const int32_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
-
+ static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
int32_t code = *cmd++;
- if (code == BR_ERROR) {
+ size_t cmdIndex = code & 0xff;
+ if (code == (int32_t) BR_ERROR) {
out << "BR_ERROR: " << (void*)(*cmd++) << endl;
return cmd;
- } else if (code < 0 || code >= N) {
+ } else if (cmdIndex >= N) {
out << "Unknown reply: " << code << endl;
return cmd;
}
+ out << kReturnStrings[cmdIndex];
- out << kReturnStrings[code];
switch (code) {
case BR_TRANSACTION:
case BR_REPLY: {
@@ -213,6 +203,11 @@
const int32_t c = *cmd++;
out << ": death cookie " << (void*)c;
} break;
+
+ default:
+ // no details to show for: BR_OK, BR_DEAD_REPLY,
+ // BR_TRANSACTION_COMPLETE, BR_FINISHED
+ break;
}
out << endl;
@@ -221,16 +216,17 @@
static const void* printCommand(TextOutput& out, const void* _cmd)
{
- static const int32_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
-
+ static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
int32_t code = *cmd++;
- if (code < 0 || code >= N) {
+ size_t cmdIndex = code & 0xff;
+
+ if (cmdIndex >= N) {
out << "Unknown command: " << code << endl;
return cmd;
}
-
- out << kCommandStrings[code];
+ out << kCommandStrings[cmdIndex];
+
switch (code) {
case BC_TRANSACTION:
case BC_REPLY: {
@@ -254,7 +250,7 @@
case BC_RELEASE:
case BC_DECREFS: {
const int32_t d = *cmd++;
- out << ": descriptor=" << (void*)d;
+ out << ": desc=" << d;
} break;
case BC_INCREFS_DONE:
@@ -267,7 +263,7 @@
case BC_ATTEMPT_ACQUIRE: {
const int32_t p = *cmd++;
const int32_t d = *cmd++;
- out << ": decriptor=" << (void*)d << ", pri=" << p;
+ out << ": desc=" << d << ", pri=" << p;
} break;
case BC_REQUEST_DEATH_NOTIFICATION:
@@ -281,6 +277,11 @@
const int32_t c = *cmd++;
out << ": death cookie " << (void*)c;
} break;
+
+ default:
+ // no details to show for: BC_REGISTER_LOOPER, BC_ENTER_LOOPER,
+ // BC_EXIT_LOOPER
+ break;
}
out << endl;
@@ -592,6 +593,7 @@
status_t IPCThreadState::attemptIncStrongHandle(int32_t handle)
{
+ LOG_REMOTEREFS("IPCThreadState::attemptIncStrongHandle(%d)\n", handle);
mOut.writeInt32(BC_ATTEMPT_ACQUIRE);
mOut.writeInt32(0); // xxx was thread priority
mOut.writeInt32(handle);
@@ -772,7 +774,7 @@
} else {
bwr.read_size = 0;
}
-
+
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
@@ -789,7 +791,7 @@
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
-
+
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
@@ -809,7 +811,7 @@
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
-
+
IF_LOG_COMMANDS() {
alog << "Our err: " << (void*)err << ", write consumed: "
<< bwr.write_consumed << " (of " << mOut.dataSize()
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 710ef94..0bee0f1 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -219,9 +219,12 @@
if (i < 0) {
return i;
}
- mSurfaceTexture->queueBuffer(i, timestamp,
+ status_t err = mSurfaceTexture->queueBuffer(i, timestamp,
&mDefaultWidth, &mDefaultHeight, &mTransformHint);
- return OK;
+ if (err != OK) {
+ LOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
+ }
+ return err;
}
int SurfaceTextureClient::query(int what, int* value) const {
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 44babcf..b8bc454 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -974,8 +974,6 @@
eglSwapBuffers(mEglDisplay, stcEglSurface);
- eglDestroySurface(mEglDisplay, stcEglSurface);
-
// Do the consumer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext));
@@ -985,6 +983,10 @@
mST->updateTexImage();
+ // We must wait until updateTexImage has been called to destroy the
+ // EGLSurface because we're in synchronous mode.
+ eglDestroySurface(mEglDisplay, stcEglSurface);
+
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp
index 4dfa578..ceca435 100644
--- a/libs/utils/Static.cpp
+++ b/libs/utils/Static.cpp
@@ -56,7 +56,9 @@
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
{
- android_writevLog(&vec, N);
+ //android_writevLog(&vec, N); <-- this is now a no-op
+ if (N != 1) LOGI("WARNING: writeLines N=%d\n", N);
+ LOGI("%.*s", vec.iov_len, (const char*) vec.iov_base);
return NO_ERROR;
}
};
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e94e50e..325193c 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -23,6 +23,7 @@
#include <limits.h>
#include <cutils/log.h>
+#include <cutils/properties.h>
#include <EGL/egl.h>
@@ -45,6 +46,39 @@
ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
+/* This function is called to check whether we run inside the emulator,
+ * and if this is the case whether GLES GPU emulation is supported.
+ *
+ * Returned values are:
+ * -1 -> not running inside the emulator
+ * 0 -> running inside the emulator, but GPU emulation not supported
+ * 1 -> running inside the emulator, GPU emulation is supported
+ * through the "emulation" config.
+ */
+static int
+checkGlesEmulationStatus(void)
+{
+ /* We're going to check for the following kernel parameters:
+ *
+ * qemu=1 -> tells us that we run inside the emulator
+ * android.qemu.gles=<number> -> tells us the GLES GPU emulation status
+ *
+ * Note that we will return <number> if we find it. This let us support
+ * more additionnal emulation modes in the future.
+ */
+ char prop[PROPERTY_VALUE_MAX];
+ int result = -1;
+
+ /* First, check for qemu=1 */
+ property_get("ro.kernel.qemu",prop,"0");
+ if (atoi(prop) != 1)
+ return -1;
+
+ /* We are in the emulator, get GPU status value */
+ property_get("ro.kernel.qemu.gles",prop,"0");
+ return atoi(prop);
+}
+
// ----------------------------------------------------------------------------
Loader::driver_t::driver_t(void* gles)
@@ -94,6 +128,15 @@
{
char line[256];
char tag[256];
+
+ /* Special case for GLES emulation */
+ if (checkGlesEmulationStatus() == 0) {
+ LOGD("Emulator without GPU support detected. Fallback to software renderer.");
+ gConfig.add( entry_t(0, 0, "android") );
+ return;
+ }
+
+ /* Otherwise, use egl.cfg */
FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
if (cfg == NULL) {
// default config
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index ddad2d3..1e43195 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -95,12 +95,12 @@
if (fgets(cmdline, sizeof(cmdline) - 1, file))
{
if (!strcmp(value, cmdline))
- sEGLTraceLevel = 1;
+ gEGLDebugLevel = 1;
}
fclose(file);
}
- if (sEGLTraceLevel > 0)
+ if (gEGLDebugLevel > 0)
{
property_get("debug.egl.debug_port", value, "5039");
const unsigned short port = (unsigned short)atoi(value);
@@ -117,7 +117,7 @@
if (sEGLTraceLevel > 0) {
setGlTraceThreadSpecific(value);
setGlThreadSpecific(&gHooksTrace);
- } else if (sEGLTraceLevel > 0 && value != &gHooksNoContext) {
+ } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
setGlTraceThreadSpecific(value);
setGlThreadSpecific(&gHooksDebug);
} else {
@@ -148,10 +148,13 @@
if (egl_tls_t::logNoContextCall()) {
LOGE("call to OpenGL ES API with no current context "
"(logged once per thread)");
- LOGE("call stack before error:");
- CallStack stack;
- stack.update();
- stack.dump();
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.egl.callstack", value, "0");
+ if (atoi(value)) {
+ CallStack stack;
+ stack.update();
+ stack.dump();
+ }
}
return 0;
}
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index 961a61e..f3c8d2c 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -14,9 +14,13 @@
** limitations under the License.
*/
+#include <stdlib.h>
#include <pthread.h>
#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <utils/CallStack.h>
#include <EGL/egl.h>
@@ -69,6 +73,13 @@
if (tls->error != error) {
LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
tls->error = error;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.egl.callstack", value, "0");
+ if (atoi(value)) {
+ CallStack stack;
+ stack.update();
+ stack.dump();
+ }
}
}
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
index ff9be3c..9e77665 100644
--- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -88,7 +88,7 @@
msg.set_arg1(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
Send(msg, cmd);
- *(DbgContext **)pthread_getspecific(dbgEGLThreadLocalStorageKey) = dbg;
+ pthread_setspecific(dbgEGLThreadLocalStorageKey, dbg);
return dbg;
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7d1bdf0..c9567d5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -22,6 +22,7 @@
#include <utils/Errors.h>
#include <utils/String8.h>
+#include <utils/Vector.h>
#include <hardware/hardware.h>
@@ -29,6 +30,7 @@
#include <EGL/egl.h>
+#include "LayerBase.h"
#include "HWComposer.h"
#include "SurfaceFlinger.h"
@@ -108,8 +110,21 @@
}
status_t HWComposer::release() const {
- int err = mHwc->set(mHwc, NULL, NULL, NULL);
- return (status_t)err;
+ if (mHwc) {
+ int err = mHwc->set(mHwc, NULL, NULL, NULL);
+ return (status_t)err;
+ }
+ return NO_ERROR;
+}
+
+status_t HWComposer::disable() {
+ if (mHwc) {
+ free(mList);
+ mList = NULL;
+ int err = mHwc->prepare(mHwc, NULL);
+ return (status_t)err;
+ }
+ return NO_ERROR;
}
size_t HWComposer::getNumLayers() const {
@@ -120,7 +135,8 @@
return mList ? mList->hwLayers : 0;
}
-void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
+void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
+ const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
if (mHwc && mList) {
result.append("Hardware Composer state:\n");
@@ -130,11 +146,12 @@
for (size_t i=0 ; i<mList->numHwLayers ; i++) {
const hwc_layer_t& l(mList->hwLayers[i]);
- snprintf(buffer, SIZE, " %8s | %08x | %08x | %02x | %04x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d]\n",
+ snprintf(buffer, SIZE, " %8s | %08x | %08x | %02x | %04x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
l.compositionType ? "OVERLAY" : "FB",
l.hints, l.flags, l.transform, l.blending,
l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
- l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom);
+ l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+ visibleLayersSortedByZ[i]->getName().string());
result.append(buffer);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 983898a..8758a80 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -25,12 +25,14 @@
#include <hardware/hwcomposer.h>
#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
namespace android {
// ---------------------------------------------------------------------------
class String8;
class SurfaceFlinger;
+class LayerBase;
class HWComposer
{
@@ -50,6 +52,9 @@
// Asks the HAL what it can do
status_t prepare() const;
+ // disable hwc until next createWorkList
+ status_t disable();
+
// commits the list
status_t commit() const;
@@ -60,7 +65,8 @@
hwc_layer_t* getLayers() const;
// for debugging
- void dump(String8& out, char* scratch, size_t SIZE) const;
+ void dump(String8& out, char* scratch, size_t SIZE,
+ const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
private:
struct cb_context {
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 603fb60..e5ce814 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -43,7 +43,7 @@
: dpy(display), contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
mFlinger(flinger), mFiltering(false),
- mNeedsFiltering(false),
+ mNeedsFiltering(false), mInOverlay(false),
mOrientation(0),
mTransactionFlags(0),
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
@@ -344,6 +344,14 @@
hwcl->handle = NULL;
}
+void LayerBase::setOverlay(bool inOverlay) {
+ mInOverlay = inOverlay;
+}
+
+bool LayerBase::isOverlay() const {
+ return mInOverlay;
+}
+
void LayerBase::setFiltering(bool filtering)
{
mFiltering = filtering;
@@ -472,12 +480,13 @@
{
const Layer::State& s(drawingState());
snprintf(buffer, SIZE,
- "+ %s %p\n"
+ "+ %s %p (%s)\n"
" "
"z=%9d, pos=(%g,%g), size=(%4d,%4d), "
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- getTypeId(), this, s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
+ getTypeId(), this, getName().string(),
+ s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
s.transform[0][0], s.transform[0][1],
@@ -553,9 +562,7 @@
sp<Client> client(mClientRef.promote());
snprintf(buffer, SIZE,
- " name=%s\n"
" client=%p, identity=%u\n",
- getName().string(),
client.get(), getIdentity());
result.append(buffer);
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d20f06a..ee50428 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -109,8 +109,10 @@
virtual const char* getTypeId() const { return "LayerBase"; }
virtual void setGeometry(hwc_layer_t* hwcl);
-
virtual void setPerFrameData(hwc_layer_t* hwcl);
+ void setOverlay(bool inOverlay);
+ bool isOverlay() const;
+
/**
* draw - performs some global clipping optimizations
@@ -242,6 +244,11 @@
// Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering;
+ // this layer is currently handled by the hwc. this is
+ // updated at composition time, always frmo the composition
+ // thread.
+ bool mInOverlay;
+
protected:
// cached during validateVisibility()
int32_t mOrientation;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 598220f..df13640 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -876,30 +876,30 @@
}
}
- // compose all surfaces
+ Region expandDirty = setupHardwareComposer(mDirtyRegion);
+ mDirtyRegion.orSelf(expandDirty);
+ mInvalidRegion.orSelf(mDirtyRegion);
composeSurfaces(mDirtyRegion);
// clear the dirty regions
mDirtyRegion.clear();
}
-void SurfaceFlinger::composeSurfaces(const Region& dirty)
+Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
{
- if (UNLIKELY(!mWormholeRegion.isEmpty())) {
- // should never happen unless the window manager has a bug
- // draw something...
- drawWormhole();
- }
-
- status_t err = NO_ERROR;
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- size_t count = layers.size();
+ Region dirtyOut(dirty);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
hwc_layer_t* const cur(hwc.getLayers());
+ if (!cur) {
+ return dirtyOut;
+ }
- LOGE_IF(cur && hwc.getNumLayers() != count,
+ const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ size_t count = layers.size();
+
+ LOGE_IF(hwc.getNumLayers() != count,
"HAL number of layers (%d) doesn't match surfaceflinger (%d)",
hwc.getNumLayers(), count);
@@ -912,57 +912,95 @@
* update the per-frame h/w composer data for each layer
* and build the transparent region of the FB
*/
- Region transparent;
- if (cur) {
- for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer(layers[i]);
- layer->setPerFrameData(&cur[i]);
- }
- err = hwc.prepare();
- LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(layers[i]);
+ layer->setPerFrameData(&cur[i]);
+ }
+ status_t err = hwc.prepare();
+ LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
- if (err == NO_ERROR) {
- for (size_t i=0 ; i<count ; i++) {
- if (cur[i].hints & HWC_HINT_CLEAR_FB) {
- const sp<LayerBase>& layer(layers[i]);
- if (layer->isOpaque()) {
- transparent.orSelf(layer->visibleRegionScreen);
- }
- }
+ if (err == NO_ERROR) {
+ Region transparent;
+ for (size_t i=0 ; i<count ; i++) {
+ // what's happening here is tricky.
+ // we want to clear all the layers with the CLEAR_FB flags
+ // that are opaque.
+ // however, since some GPU have are efficient at preserving
+ // the backbuffer, we want to take advantage of that so we do the
+ // clear only in the dirty region (other areas will be preserved
+ // on those GPUs).
+ // NOTE: on non backbuffer preserving GPU, the dirty region
+ // has already been expanded as needed, so the code is correct
+ // there too.
+ // However, the content of the framebuffer cannot be trusted when
+ // we switch to/from FB/OVERLAY, in which case we need to
+ // expand the dirty region to those areas too.
+ //
+ // Also we want to make sure to not clear areas that belong to
+ // layers above that won't redraw (we would just erasing them),
+ // that is, we can't erase anything outside the dirty region.
+
+ const sp<LayerBase>& layer(layers[i]);
+ if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
+ transparent.orSelf(layer->visibleRegionScreen);
}
- /*
- * clear the area of the FB that need to be transparent
- */
- transparent.andSelf(dirty);
- if (!transparent.isEmpty()) {
- glClearColor(0,0,0,0);
- Region::const_iterator it = transparent.begin();
- Region::const_iterator const end = transparent.end();
- const int32_t height = hw.getHeight();
- while (it != end) {
- const Rect& r(*it++);
- const GLint sy = height - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glClear(GL_COLOR_BUFFER_BIT);
- }
+ bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) &&
+ !(cur[i].flags & HWC_SKIP_LAYER);
+
+ if (isOverlay != layer->isOverlay()) {
+ // we transitioned to/from overlay, so add this layer
+ // to the dirty region so the framebuffer can be either
+ // cleared or redrawn.
+ dirtyOut.orSelf(layer->visibleRegionScreen);
+ }
+ layer->setOverlay(isOverlay);
+ }
+
+
+ /*
+ * clear the area of the FB that need to be transparent
+ */
+ // don't erase stuff outside the dirty region
+ transparent.andSelf(dirtyOut);
+ if (!transparent.isEmpty()) {
+ glClearColor(0,0,0,0);
+ Region::const_iterator it = transparent.begin();
+ Region::const_iterator const end = transparent.end();
+ const int32_t height = hw.getHeight();
+ while (it != end) {
+ const Rect& r(*it++);
+ const GLint sy = height - (r.top + r.height());
+ glScissor(r.left, sy, r.width(), r.height());
+ glClear(GL_COLOR_BUFFER_BIT);
}
}
}
+ return dirtyOut;
+}
+void SurfaceFlinger::composeSurfaces(const Region& dirty)
+{
+ if (UNLIKELY(!mWormholeRegion.isEmpty())) {
+ // should never happen unless the window manager has a bug
+ // draw something...
+ drawWormhole();
+ }
+
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ HWComposer& hwc(hw.getHwComposer());
+ hwc_layer_t* const cur(hwc.getLayers());
/*
* and then, render the layers targeted at the framebuffer
*/
+ const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
- if (cur) {
- if ((cur[i].compositionType != HWC_FRAMEBUFFER) &&
+ if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER) &&
!(cur[i].flags & HWC_SKIP_LAYER)) {
- // skip layers handled by the HAL
- continue;
- }
+ continue;
}
-
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
@@ -1583,7 +1621,7 @@
hwc.initCheck()==NO_ERROR ? "present" : "not present",
(mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
result.append(buffer);
- hwc.dump(result, buffer, SIZE);
+ hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
/*
* Dump gralloc state
@@ -2099,6 +2137,12 @@
// we're already off
return NO_ERROR;
}
+
+ // turn off hwc while we're doing the animation
+ hw.getHwComposer().disable();
+ // and make sure to turn it back on (if needed) next time we compose
+ invalidateHwcGeometry();
+
if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {
electronBeamOffAnimationImplLocked();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5f8eb08..126ca39 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -277,6 +277,7 @@
void handleWorkList();
void handleRepaint();
void postFramebuffer();
+ Region setupHardwareComposer(const Region& dirty);
void composeSurfaces(const Region& dirty);
void repaintEverything();