summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/gui/ISurfaceComposer.h1
-rw-r--r--include/gui/SurfaceComposerClient.h5
-rw-r--r--libs/gui/SurfaceComposerClient.cpp23
-rw-r--r--opengl/libs/EGL/eglApi.cpp53
-rw-r--r--services/surfaceflinger/LayerScreenshot.cpp3
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp95
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h11
7 files changed, 149 insertions, 42 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 5d2d8d7..002aafc 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -46,6 +46,7 @@ public:
// flags for setTransactionState()
enum {
eSynchronous = 0x01,
+ eAnimation = 0x02,
};
enum {
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 581ec8d..21d16a9 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -101,10 +101,13 @@ public:
//! Open a composer transaction on all active SurfaceComposerClients.
static void openGlobalTransaction();
-
+
//! Close a composer transaction on all active SurfaceComposerClients.
static void closeGlobalTransaction(bool synchronous = false);
+ //! Flag the currently open transaction as an animation transaction.
+ static void setAnimationTransaction();
+
status_t hide(SurfaceID id);
status_t show(SurfaceID id);
status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3efd086..8586ed2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -115,12 +115,15 @@ class Composer : public Singleton<Composer>
SortedVector<ComposerState> mComposerStates;
SortedVector<DisplayState > mDisplayStates;
uint32_t mForceSynchronous;
+ bool mAnimation;
Composer() : Singleton<Composer>(),
- mForceSynchronous(0)
+ mForceSynchronous(0),
+ mAnimation(false)
{ }
void closeGlobalTransactionImpl(bool synchronous);
+ void setAnimationTransactionImpl();
layer_state_t* getLayerStateLocked(
const sp<SurfaceComposerClient>& client, SurfaceID id);
@@ -159,6 +162,10 @@ public:
const Rect& layerStackRect,
const Rect& displayRect);
+ static void setAnimationTransaction() {
+ Composer::getInstance().setAnimationTransactionImpl();
+ }
+
static void closeGlobalTransaction(bool synchronous) {
Composer::getInstance().closeGlobalTransactionImpl(synchronous);
}
@@ -194,12 +201,22 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) {
if (synchronous || mForceSynchronous) {
flags |= ISurfaceComposer::eSynchronous;
}
+ if (mAnimation) {
+ flags |= ISurfaceComposer::eAnimation;
+ }
+
mForceSynchronous = false;
+ mAnimation = false;
}
sm->setTransactionState(transaction, displayTransaction, flags);
}
+void Composer::setAnimationTransactionImpl() {
+ Mutex::Autolock _l(mLock);
+ mAnimation = true;
+}
+
layer_state_t* Composer::getLayerStateLocked(
const sp<SurfaceComposerClient>& client, SurfaceID id) {
@@ -471,6 +488,10 @@ void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
Composer::closeGlobalTransaction(synchronous);
}
+void SurfaceComposerClient::setAnimationTransaction() {
+ Composer::setAnimationTransaction();
+}
+
// ----------------------------------------------------------------------------
status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 92023ba..c352401 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -204,6 +204,59 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso) {
+ if (attrib_list) {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.egl.force_msaa", value, "false");
+
+ if (!strcmp(value, "true")) {
+ size_t attribCount = 0;
+ EGLint attrib = attrib_list[0];
+
+ // Only enable MSAA if the context is OpenGL ES 2.0 and
+ // if a depth buffer is requested
+ const EGLint *attribRendererable = NULL;
+ const EGLint *attribCaveat = NULL;
+
+ // Count the number of attributes and look for
+ // EGL_RENDERABLE_TYPE and ELG_DEPTH_SIZE
+ while (attrib != EGL_NONE) {
+ attrib = attrib_list[attribCount];
+ switch (attrib) {
+ case EGL_RENDERABLE_TYPE:
+ attribRendererable = &attrib_list[attribCount];
+ break;
+ case EGL_CONFIG_CAVEAT:
+ attribCaveat = &attrib_list[attribCount];
+ break;
+ }
+ attribCount++;
+ }
+
+ if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
+ (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
+
+ // Insert 2 extra attributes to force-enable MSAA 4x
+ EGLint aaAttribs[attribCount + 4];
+ aaAttribs[0] = EGL_SAMPLE_BUFFERS;
+ aaAttribs[1] = 1;
+ aaAttribs[2] = EGL_SAMPLES;
+ aaAttribs[3] = 4;
+
+ memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
+
+ EGLint numConfigAA;
+ EGLBoolean resAA = cnx->egl.eglChooseConfig(
+ dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
+
+ if (resAA == EGL_TRUE && numConfigAA > 0) {
+ ALOGD("Enabling MSAA 4x");
+ *num_config = numConfigAA;
+ return resAA;
+ }
+ }
+ }
+ }
+
res = cnx->egl.eglChooseConfig(
dp->disp.dpy, attrib_list, configs, config_size, num_config);
}
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index 1aa8c09..0fd744f 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -122,13 +122,14 @@ void LayerScreenshot::onDraw(const sp<const DisplayDevice>& hw, const Region& cl
} else {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(alpha, alpha, alpha, alpha);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
LayerMesh mesh;
computeGeometry(hw, &mesh);
+ glColor4f(alpha, alpha, alpha, alpha);
+
glDisable(GL_TEXTURE_EXTERNAL_OES);
glEnable(GL_TEXTURE_2D);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 492d1cf..13b2c6b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -86,7 +86,8 @@ const String16 sDump("android.permission.DUMP");
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
- mTransationPending(false),
+ mTransactionPending(false),
+ mAnimTransactionPending(false),
mLayersRemoved(false),
mRepaintEverything(0),
mBootTime(systemTime()),
@@ -506,7 +507,7 @@ status_t SurfaceFlinger::readyToRun()
// or when a texture is (asynchronously) destroyed, and for that
// we need a valid surface, so it's convenient to use the main display
// for that.
- sp<const DisplayDevice> hw = getDefaultDisplayDevice();
+ sp<const DisplayDevice> hw(getDefaultDisplayDevice());
// initialize OpenGL ES
DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
@@ -1125,7 +1126,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// Call makeCurrent() on the primary display so we can
// be sure that nothing associated with this display
// is current.
- const sp<const DisplayDevice>& hw(getDefaultDisplayDevice());
+ const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
mDisplays.removeItem(draw.keyAt(i));
getHwComposer().disconnectDisplay(draw[i].type);
@@ -1149,7 +1150,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
continue;
}
- const sp<DisplayDevice>& disp(getDisplayDevice(display));
+ const sp<DisplayDevice> disp(getDisplayDevice(display));
if (disp != NULL) {
if (state.layerStack != draw[i].layerStack) {
disp->setLayerStack(state.layerStack);
@@ -1264,7 +1265,8 @@ void SurfaceFlinger::commitTransaction()
}
mDrawingState = mCurrentState;
- mTransationPending = false;
+ mTransactionPending = false;
+ mAnimTransactionPending = false;
mTransactionCV.broadcast();
}
@@ -1665,6 +1667,21 @@ void SurfaceFlinger::setTransactionState(
Mutex::Autolock _l(mStateLock);
uint32_t transactionFlags = 0;
+ if (flags & eAnimation) {
+ // For window updates that are part of an animation we must wait for
+ // previous animation "frames" to be handled.
+ while (mAnimTransactionPending) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, 500 * 1000);
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // caller after a few hundred microseconds.
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+ mAnimTransactionPending = false;
+ break;
+ }
+ }
+ }
+
size_t count = displays.size();
for (size_t i=0 ; i<count ; i++) {
const DisplayState& s(displays[i]);
@@ -1685,15 +1702,18 @@ void SurfaceFlinger::setTransactionState(
// if this is a synchronous transaction, wait for it to take effect
// before returning.
if (flags & eSynchronous) {
- mTransationPending = true;
+ mTransactionPending = true;
+ }
+ if (flags & eAnimation) {
+ mAnimTransactionPending = true;
}
- while (mTransationPending) {
+ while (mTransactionPending) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
// called after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
- mTransationPending = false;
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+ mTransactionPending = false;
break;
}
}
@@ -2023,48 +2043,48 @@ void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
void SurfaceFlinger::unblank(const sp<IBinder>& display) {
class MessageScreenAcquired : public MessageBase {
- SurfaceFlinger* mFlinger;
- const sp<DisplayDevice>& mHw;
+ SurfaceFlinger& mFlinger;
+ sp<IBinder> mDisplay;
public:
- MessageScreenAcquired(SurfaceFlinger* flinger,
- const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+ MessageScreenAcquired(SurfaceFlinger& flinger,
+ const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
virtual bool handler() {
- mFlinger->onScreenAcquired(mHw);
+ const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+ if (hw == NULL) {
+ ALOGE("Attempt to unblank null display %p", mDisplay.get());
+ } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+ ALOGW("Attempt to unblank virtual display");
+ } else {
+ mFlinger.onScreenAcquired(hw);
+ }
return true;
}
};
- const sp<DisplayDevice>& hw = getDisplayDevice(display);
- if (hw == NULL) {
- ALOGE("Attempt to unblank null display %p", display.get());
- } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
- ALOGW("Attempt to unblank virtual display");
- } else {
- sp<MessageBase> msg = new MessageScreenAcquired(this, hw);
- postMessageSync(msg);
- }
+ sp<MessageBase> msg = new MessageScreenAcquired(*this, display);
+ postMessageSync(msg);
}
void SurfaceFlinger::blank(const sp<IBinder>& display) {
class MessageScreenReleased : public MessageBase {
- SurfaceFlinger* mFlinger;
- const sp<DisplayDevice>& mHw;
+ SurfaceFlinger& mFlinger;
+ sp<IBinder> mDisplay;
public:
- MessageScreenReleased(SurfaceFlinger* flinger,
- const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+ MessageScreenReleased(SurfaceFlinger& flinger,
+ const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
virtual bool handler() {
- mFlinger->onScreenReleased(mHw);
+ const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+ if (hw == NULL) {
+ ALOGE("Attempt to blank null display %p", mDisplay.get());
+ } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+ ALOGW("Attempt to blank virtual display");
+ } else {
+ mFlinger.onScreenReleased(hw);
+ }
return true;
}
};
- const sp<DisplayDevice>& hw = getDisplayDevice(display);
- if (hw == NULL) {
- ALOGE("Attempt to blank null display %p", display.get());
- } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
- ALOGW("Attempt to blank virtual display");
- } else {
- sp<MessageBase> msg = new MessageScreenReleased(this, hw);
- postMessageSync(msg);
- }
+ sp<MessageBase> msg = new MessageScreenReleased(*this, display);
+ postMessageSync(msg);
}
// ---------------------------------------------------------------------------
@@ -2339,6 +2359,7 @@ void SurfaceFlinger::dumpAllLocked(
const Vector< sp<LayerBase> >&
SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
+ // Note: mStateLock is held here
return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6d36719..de97167 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -327,10 +327,13 @@ private:
// called when starting, or restarting after system_server death
void initializeDisplays();
+ // NOTE: can only be called from the main thread or with mStateLock held
sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
return mDisplays.valueFor(dpy);
}
- const sp<DisplayDevice>& getDisplayDevice(const wp<IBinder>& dpy) {
+
+ // NOTE: can only be called from the main thread or with mStateLock held
+ sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
return mDisplays.valueFor(dpy);
}
@@ -398,7 +401,8 @@ private:
volatile int32_t mTransactionFlags;
Condition mTransactionCV;
SortedVector<sp<LayerBase> > mLayerPurgatory;
- bool mTransationPending;
+ bool mTransactionPending;
+ bool mAnimTransactionPending;
Vector<sp<LayerBase> > mLayersPendingRemoval;
// protected by mStateLock (but we could use another lock)
@@ -424,6 +428,9 @@ private:
State mDrawingState;
bool mVisibleRegionsDirty;
bool mHwWorkListDirty;
+
+ // this may only be written from the main thread with mStateLock held
+ // it may be read from other threads with mStateLock held
DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
// don't use a lock for these, we don't care