Merge "Fix deadlock when cleaning objects in eglTerminate"
diff --git a/include/utils/Tokenizer.h b/include/utils/Tokenizer.h
index c7db5fb..bb25f37 100644
--- a/include/utils/Tokenizer.h
+++ b/include/utils/Tokenizer.h
@@ -28,7 +28,8 @@
* A simple tokenizer for loading and parsing ASCII text files line by line.
*/
class Tokenizer {
- Tokenizer(const String8& filename, FileMap* fileMap, char* buffer, size_t length);
+ Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
+ bool ownBuffer, size_t length);
public:
~Tokenizer();
@@ -42,6 +43,15 @@
static status_t open(const String8& filename, Tokenizer** outTokenizer);
/**
+ * Prepares to tokenize the contents of a string.
+ *
+ * Returns NO_ERROR and a tokenizer for the string, if successful.
+ * Otherwise returns an error and sets outTokenizer to NULL.
+ */
+ static status_t fromContents(const String8& filename,
+ const char* contents, Tokenizer** outTokenizer);
+
+ /**
* Returns true if at the end of the file.
*/
inline bool isEof() const { return mCurrent == getEnd(); }
@@ -111,6 +121,7 @@
String8 mFilename;
FileMap* mFileMap;
char* mBuffer;
+ bool mOwnBuffer;
size_t mLength;
const char* mCurrent;
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index a2429c0..637c146 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -45,7 +45,8 @@
#define ATRACE_TAG_GRAPHICS (1<<1)
#define ATRACE_TAG_INPUT (1<<2)
#define ATRACE_TAG_VIEW (1<<3)
-#define ATRACE_TAG_LAST ATRACE_TAG_VIEW
+#define ATRACE_TAG_WEBVIEW (1<<4)
+#define ATRACE_TAG_LAST ATRACE_TAG_WEBVIEW
#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 9fa412c..5399e52 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -73,10 +73,11 @@
sp<ProcessState> ProcessState::self()
{
- if (gProcess != NULL) return gProcess;
-
- AutoMutex _l(gProcessMutex);
- if (gProcess == NULL) gProcess = new ProcessState;
+ Mutex::Autolock _l(gProcessMutex);
+ if (gProcess != NULL) {
+ return gProcess;
+ }
+ gProcess = new ProcessState;
return gProcess;
}
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 01d08b7..ece0494 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -57,9 +57,12 @@
#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
#define ATRACE_BUFFER_INDEX(index) \
- char ___traceBuf[1024]; \
- snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), (index)); \
- android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);
+ if (ATRACE_ENABLED()) { \
+ char ___traceBuf[1024]; \
+ snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), \
+ (index)); \
+ android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
+ }
namespace android {
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 0fa9ca1..a6ee971 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -344,6 +344,18 @@
glDeleteTextures(1, &mTexName);
}
+ // Because we're giving up the EGLDisplay we need to free all the EGLImages
+ // that are associated with it. They'll be recreated when the
+ // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a
+ // new EGLDisplay).
+ for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ EGLImageKHR img = mEGLSlots[i].mEglImage;
+ if (img != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mEglDisplay, img);
+ mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+ }
+ }
+
mEglDisplay = EGL_NO_DISPLAY;
mEglContext = EGL_NO_CONTEXT;
mAttached = false;
@@ -542,28 +554,16 @@
// decoder, camera, etc.) would simply not use a crop rectangle (or at
// least not tell the framework about it) so that the GPU can do the
// correct edge behavior.
- int xshrink = 0, yshrink = 0;
- if (mCurrentCrop.left > 0) {
- tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
- xshrink++;
- } else {
- tx = 0.0f;
- }
- if (mCurrentCrop.right < int32_t(buf->getWidth())) {
- xshrink++;
- }
- if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
- ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
- float(buf->getHeight());
- yshrink++;
- } else {
- ty = 0.0f;
- }
- if (mCurrentCrop.top > 0) {
- yshrink++;
- }
- sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
- sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
+ const float shrinkAmount = 1.0f; // the amount that each edge is shrunk
+
+ tx = (float(mCurrentCrop.left) + shrinkAmount) /
+ float(buf->getWidth());
+ ty = (float(buf->getHeight() - mCurrentCrop.bottom) +
+ shrinkAmount) / float(buf->getHeight());
+ sx = (float(mCurrentCrop.width()) - (2.0f * shrinkAmount)) /
+ float(buf->getWidth());
+ sy = (float(mCurrentCrop.height()) - (2.0f * shrinkAmount)) /
+ float(buf->getHeight());
} else {
tx = 0.0f;
ty = 0.0f;
@@ -680,13 +680,12 @@
if (slotIndex == mCurrentTexture) {
mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
}
- if (mEGLSlots[slotIndex].mEglImage != EGL_NO_IMAGE_KHR) {
- EGLImageKHR img = mEGLSlots[slotIndex].mEglImage;
- if (img != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mEglDisplay, img);
- }
- mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
+ EGLImageKHR img = mEGLSlots[slotIndex].mEglImage;
+ if (img != EGL_NO_IMAGE_KHR) {
+ ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
+ eglDestroyImageKHR(mEglDisplay, img);
}
+ mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
}
void SurfaceTexture::abandon() {
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index aa1f94e..b576ca5 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -580,13 +580,13 @@
// This accounts for the 1 texel shrink for each edge that's included in the
// transform matrix to avoid texturing outside the crop region.
- EXPECT_EQ(.5f, mtx[0]);
+ EXPECT_EQ(.375f, mtx[0]);
EXPECT_EQ(0.f, mtx[1]);
EXPECT_EQ(0.f, mtx[2]);
EXPECT_EQ(0.f, mtx[3]);
EXPECT_EQ(0.f, mtx[4]);
- EXPECT_EQ(-.5f, mtx[5]);
+ EXPECT_EQ(-.375f, mtx[5]);
EXPECT_EQ(0.f, mtx[6]);
EXPECT_EQ(0.f, mtx[7]);
@@ -595,7 +595,7 @@
EXPECT_EQ(1.f, mtx[10]);
EXPECT_EQ(0.f, mtx[11]);
- EXPECT_EQ(0.f, mtx[12]);
+ EXPECT_EQ(.125f, mtx[12]);
EXPECT_EQ(.5f, mtx[13]);
EXPECT_EQ(0.f, mtx[14]);
EXPECT_EQ(1.f, mtx[15]);
diff --git a/libs/utils/Tokenizer.cpp b/libs/utils/Tokenizer.cpp
index efda2bf..7067533 100644
--- a/libs/utils/Tokenizer.cpp
+++ b/libs/utils/Tokenizer.cpp
@@ -35,15 +35,18 @@
return strchr(delimiters, ch) != NULL;
}
-Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer, size_t length) :
+Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
+ bool ownBuffer, size_t length) :
mFilename(filename), mFileMap(fileMap),
- mBuffer(buffer), mLength(length), mCurrent(buffer), mLineNumber(1) {
+ mBuffer(buffer), mOwnBuffer(ownBuffer), mLength(length),
+ mCurrent(buffer), mLineNumber(1) {
}
Tokenizer::~Tokenizer() {
if (mFileMap) {
mFileMap->release();
- } else {
+ }
+ if (mOwnBuffer) {
delete[] mBuffer;
}
}
@@ -65,6 +68,7 @@
size_t length = size_t(stat.st_size);
FileMap* fileMap = new FileMap();
+ bool ownBuffer = false;
char* buffer;
if (fileMap->create(NULL, fd, 0, length, true)) {
fileMap->advise(FileMap::SEQUENTIAL);
@@ -77,6 +81,7 @@
// The length we obtained from stat is wrong too (it will always be 4096)
// so we must trust that read will read the entire file.
buffer = new char[length];
+ ownBuffer = true;
ssize_t nrd = read(fd, buffer, length);
if (nrd < 0) {
result = -errno;
@@ -89,7 +94,7 @@
}
if (!result) {
- *outTokenizer = new Tokenizer(filename, fileMap, buffer, length);
+ *outTokenizer = new Tokenizer(filename, fileMap, buffer, ownBuffer, length);
}
}
close(fd);
@@ -97,6 +102,13 @@
return result;
}
+status_t Tokenizer::fromContents(const String8& filename,
+ const char* contents, Tokenizer** outTokenizer) {
+ *outTokenizer = new Tokenizer(filename, NULL,
+ const_cast<char*>(contents), false, strlen(contents));
+ return OK;
+}
+
String8 Tokenizer::getLocation() const {
String8 result;
result.appendFormat("%s:%d", mFilename.string(), mLineNumber);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 93dd3a4..f220de3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -87,7 +87,6 @@
mHwWorkListDirty(false),
mElectronBeamAnimationMode(0),
mDebugRegion(0),
- mDebugBackground(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
mDebugDisableTransformHint(0),
@@ -111,9 +110,6 @@
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
- property_get("debug.sf.showbackground", value, "0");
- mDebugBackground = atoi(value);
-
#ifdef DDMS_DEBUGGING
property_get("debug.sf.ddms", value, "0");
mDebugDDMS = atoi(value);
@@ -123,7 +119,6 @@
#endif
ALOGI_IF(mDebugRegion, "showupdates enabled");
- ALOGI_IF(mDebugBackground, "showbackground enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
@@ -902,9 +897,20 @@
if (fbLayerCount) {
// Never touch the framebuffer if we don't have any framebuffer layers
- if (!mWormholeRegion.isEmpty()) {
- // can happen with SurfaceView
- drawWormhole();
+ if (hwc.getLayerCount(HWC_OVERLAY)) {
+ // when using overlays, we assume a fully transparent framebuffer
+ // NOTE: we could reduce how much we need to clear, for instance
+ // remove where there are opaque FB layers. however, on some
+ // GPUs doing a "clean slate" glClear might be more efficient.
+ // We'll revisit later if needed.
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ } else {
+ // screen is already cleared here
+ if (!mWormholeRegion.isEmpty()) {
+ // can happen with SurfaceView
+ drawWormhole();
+ }
}
/*
@@ -919,9 +925,11 @@
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
- if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
- if ((cur[i].hints & HWC_HINT_CLEAR_FB)
+ if (cur && (cur[i].compositionType == HWC_OVERLAY)) {
+ if (i && (cur[i].hints & HWC_HINT_CLEAR_FB)
&& layer->isOpaque()) {
+ // never clear the very first layer since we're
+ // guaranteed the FB is already cleared
layer->clearWithOpenGL(clip);
}
continue;
@@ -988,25 +996,9 @@
return;
glDisable(GL_TEXTURE_EXTERNAL_OES);
+ glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
-
- if (CC_LIKELY(!mDebugBackground)) {
- glDisable(GL_TEXTURE_2D);
- glColor4f(0,0,0,0);
- } else {
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const int32_t width = hw.getWidth();
- const int32_t height = hw.getHeight();
- const GLfloat tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
- glTexCoordPointer(2, GL_FLOAT, 0, tcoords);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
- }
+ glColor4f(0,0,0,0);
GLfloat vertices[4][2];
glVertexPointer(2, GL_FLOAT, 0, vertices);
@@ -1024,11 +1016,6 @@
vertices[3][1] = r.bottom;
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisable(GL_TEXTURE_2D);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
}
status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
@@ -1714,10 +1701,6 @@
invalidateHwcGeometry();
repaintEverything();
return NO_ERROR;
- case 1003: // SHOW_BACKGROUND
- n = data.readInt32();
- mDebugBackground = n ? 1 : 0;
- return NO_ERROR;
case 1004:{ // repaint everything
repaintEverything();
return NO_ERROR;
@@ -1746,7 +1729,7 @@
reply->writeInt32(0);
reply->writeInt32(0);
reply->writeInt32(mDebugRegion);
- reply->writeInt32(mDebugBackground);
+ reply->writeInt32(0);
reply->writeInt32(mDebugDisableHWC);
return NO_ERROR;
case 1013: {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1aea452..d9c2033 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -350,7 +350,7 @@
void debugFlashRegions();
void drawWormhole() const;
-
+
void listLayersLocked(const Vector<String16>& args, size_t& index,
String8& result, char* buffer, size_t SIZE) const;
void dumpStatsLocked(const Vector<String16>& args, size_t& index,
@@ -402,7 +402,6 @@
// don't use a lock for these, we don't care
int mDebugRegion;
- int mDebugBackground;
int mDebugDDMS;
int mDebugDisableHWC;
int mDebugDisableTransformHint;