Merge "Added an EGLTest for eglTerminate"
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index 9725822..8caf1af 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -70,6 +70,8 @@
void spawnPooledThread(bool isMain);
+ status_t setThreadPoolMaxThreadCount(size_t maxThreads);
+
private:
friend class IPCThreadState;
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 1a0d779..3699cdf 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -257,6 +257,12 @@
// before the outstanding accesses have completed.
status_t syncForReleaseLocked(EGLDisplay dpy);
+ // The default consumer usage flags that SurfaceTexture always sets on its
+ // BufferQueue instance; these will be OR:d with any additional flags passed
+ // from the SurfaceTexture user. In particular, SurfaceTexture will always
+ // consume buffers as hardware textures.
+ static const uint32_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
+
// mCurrentTextureBuf is the graphic buffer of the current texture. It's
// possible that this buffer is not associated with any buffer slot, so we
// must track it separately in order to support the getCurrentBuffer method.
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index c0e90b3..6644751 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -26,6 +26,7 @@
#include <utils/RefBase.h>
#include <utils/threads.h>
+#include <utils/KeyedVector.h>
struct ANativeWindow_Buffer;
@@ -113,6 +114,11 @@
void freeAllBuffers();
int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
+ struct BufferSlot {
+ sp<GraphicBuffer> buffer;
+ Region dirtyRegion;
+ };
+
// mSurfaceTexture is the interface to the surface texture server. All
// operations on the surface texture client ultimately translate into
// interactions with the server using this interface.
@@ -124,7 +130,7 @@
// slot that has not yet been used. The buffer allocated to a slot will also
// be replaced if the requested buffer usage or geometry differs from that
// of the buffer allocated to a slot.
- sp<GraphicBuffer> mSlots[NUM_BUFFER_SLOTS];
+ BufferSlot mSlots[NUM_BUFFER_SLOTS];
// mReqWidth is the buffer width that will be requested at the next dequeue
// operation. It is initialized to 1.
@@ -189,8 +195,10 @@
// must be used from the lock/unlock thread
sp<GraphicBuffer> mLockedBuffer;
sp<GraphicBuffer> mPostedBuffer;
- mutable Region mOldDirtyRegion;
bool mConnectedToCpu;
+
+ // must be accessed from lock/unlock thread only
+ Region mDirtyRegion;
};
}; // namespace android
diff --git a/include/media/hardware/CryptoAPI.h b/include/media/hardware/CryptoAPI.h
index 81d9601..810a443 100644
--- a/include/media/hardware/CryptoAPI.h
+++ b/include/media/hardware/CryptoAPI.h
@@ -22,6 +22,7 @@
namespace android {
+struct AString;
struct CryptoPlugin;
struct CryptoFactory {
@@ -63,6 +64,12 @@
// media data of the given mime type.
virtual bool requiresSecureDecoderComponent(const char *mime) const = 0;
+ // If the error returned falls into the range
+ // ERROR_DRM_VENDOR_MIN..ERROR_DRM_VENDOR_MAX, errorDetailMsg should be
+ // filled in with an appropriate string.
+ // At the java level these special errors will then trigger a
+ // MediaCodec.CryptoException that gives clients access to both
+ // the error code and the errorDetailMsg.
virtual status_t decrypt(
bool secure,
const uint8_t key[16],
@@ -70,7 +77,8 @@
Mode mode,
const void *srcPtr,
const SubSample *subSamples, size_t numSubSamples,
- void *dstPtr) = 0;
+ void *dstPtr,
+ AString *errorDetailMsg) = 0;
private:
CryptoPlugin(const CryptoPlugin &);
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 8d76533..421bdda 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -96,6 +96,11 @@
class SpannerBase
{
public:
+ SpannerBase()
+ : lhs_head(max_value), lhs_tail(max_value),
+ rhs_head(max_value), rhs_tail(max_value) {
+ }
+
enum {
lhs_before_rhs = 0,
lhs_after_rhs = 1,
@@ -158,12 +163,16 @@
public:
inline Spanner(const region& lhs, const region& rhs)
- : lhs(lhs), rhs(rhs)
+ : lhs(lhs), rhs(rhs)
{
- SpannerBase::lhs_head = lhs.rects->top + lhs.dy;
- SpannerBase::lhs_tail = lhs.rects->bottom + lhs.dy;
- SpannerBase::rhs_head = rhs.rects->top + rhs.dy;
- SpannerBase::rhs_tail = rhs.rects->bottom + rhs.dy;
+ if (lhs.count) {
+ SpannerBase::lhs_head = lhs.rects->top + lhs.dy;
+ SpannerBase::lhs_tail = lhs.rects->bottom + lhs.dy;
+ }
+ if (rhs.count) {
+ SpannerBase::rhs_head = rhs.rects->top + rhs.dy;
+ SpannerBase::rhs_tail = rhs.rects->bottom + rhs.dy;
+ }
}
inline bool isDone() const {
@@ -221,20 +230,28 @@
inline void prepare(int inside) {
if (inside == SpannerBase::lhs_before_rhs) {
- SpannerBase::lhs_head = lhs.rects->left + lhs.dx;
- SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+ if (lhs.count) {
+ SpannerBase::lhs_head = lhs.rects->left + lhs.dx;
+ SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+ }
SpannerBase::rhs_head = max_value;
SpannerBase::rhs_tail = max_value;
} else if (inside == SpannerBase::lhs_after_rhs) {
SpannerBase::lhs_head = max_value;
SpannerBase::lhs_tail = max_value;
- SpannerBase::rhs_head = rhs.rects->left + rhs.dx;
- SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+ if (rhs.count) {
+ SpannerBase::rhs_head = rhs.rects->left + rhs.dx;
+ SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+ }
} else {
- SpannerBase::lhs_head = lhs.rects->left + lhs.dx;
- SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
- SpannerBase::rhs_head = rhs.rects->left + rhs.dx;
- SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+ if (lhs.count) {
+ SpannerBase::lhs_head = lhs.rects->left + lhs.dx;
+ SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+ }
+ if (rhs.count) {
+ SpannerBase::rhs_head = rhs.rects->left + rhs.dx;
+ SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+ }
}
}
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..d95fd6f 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;
}
@@ -294,6 +295,15 @@
}
}
+status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
+ status_t result = NO_ERROR;
+ if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) == -1) {
+ result = -errno;
+ ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
+ }
+ return result;
+}
+
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 01d08b7..a6403d4 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 {
@@ -447,7 +450,6 @@
(uint32_t(buffer->format) != format) ||
((uint32_t(buffer->usage) & usage) != usage))
{
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
status_t error;
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(
@@ -531,8 +533,12 @@
ATRACE_CALL();
ATRACE_BUFFER_INDEX(buf);
- ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d]", buf, timestamp,
- crop.left, crop.top, crop.right, crop.bottom);
+ ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d]", buf,
+ mSlots[buf].mTimestamp,
+ mSlots[buf].mCrop.left,
+ mSlots[buf].mCrop.top,
+ mSlots[buf].mCrop.right,
+ mSlots[buf].mCrop.bottom);
sp<ConsumerListener> listener;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 0fa9ca1..a6e8dbf 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -150,6 +150,7 @@
strerror(-err), err);
} else {
mBufferQueue->setConsumerName(mName);
+ mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}
}
@@ -344,6 +345,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 +555,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 +681,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() {
@@ -721,6 +721,7 @@
status_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
Mutex::Autolock lock(mMutex);
+ usage |= DEFAULT_USAGE_FLAGS;
return mBufferQueue->setConsumerUsageBits(usage);
}
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 99c025f..b37d821 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -171,7 +171,7 @@
result);
return result;
}
- sp<GraphicBuffer>& gbuf(mSlots[buf]);
+ sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
@@ -204,7 +204,8 @@
android_native_buffer_t* buffer) const {
bool dumpedState = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) {
+ if (mSlots[i].buffer != NULL &&
+ mSlots[i].buffer->handle == buffer->handle) {
return i;
}
}
@@ -586,7 +587,7 @@
void SurfaceTextureClient::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i] = 0;
+ mSlots[i].buffer = 0;
}
}
@@ -691,19 +692,32 @@
if (canCopyBack) {
// copy the area that is invalid and not repainted this round
- const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+ const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback);
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds);
+ mDirtyRegion.clear();
+ Mutex::Autolock lock(mMutex);
+ for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
+ mSlots[i].dirtyRegion.clear();
+ }
}
- // keep track of the are of the buffer that is "clean"
- // (ie: that will be redrawn)
- mOldDirtyRegion = newDirtyRegion;
+ { // scope for the lock
+ Mutex::Autolock lock(mMutex);
+ int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
+ if (backBufferSlot >= 0) {
+ Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
+ mDirtyRegion.subtract(dirtyRegion);
+ dirtyRegion = newDirtyRegion;
+ }
+ }
+
+ mDirtyRegion.orSelf(newDirtyRegion);
if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds();
}
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/ui/Region.cpp b/libs/ui/Region.cpp
index 6e2e731..2c7cdf0 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -619,7 +619,15 @@
}
Region::const_iterator Region::end() const {
- return isRect() ? ((&mBounds) + 1) : (mStorage.array() + mStorage.size());
+ if (isRect()) {
+ if (isEmpty()) {
+ return &mBounds;
+ } else {
+ return &mBounds + 1;
+ }
+ } else {
+ return mStorage.array() + mStorage.size();
+ }
}
Rect const* Region::getArray(size_t* count) const {
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/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 2e08f24..f2e3897 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -70,8 +70,7 @@
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
egl_display_t::egl_display_t() :
- magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0),
- mWakeCount(0), mHibernating(false), mAttemptHibernation(false) {
+ magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) {
}
egl_display_t::~egl_display_t() {
@@ -253,6 +252,9 @@
*major = VERSION_MAJOR;
if (minor != NULL)
*minor = VERSION_MINOR;
+
+ mHibernation.setDisplayValid(true);
+
return EGL_TRUE;
}
@@ -282,6 +284,8 @@
res = EGL_TRUE;
}
+ mHibernation.setDisplayValid(false);
+
// Mark all objects remaining in the list as terminated, unless
// there are no reference to them, it which case, we're free to
// delete them.
@@ -351,8 +355,7 @@
if (result == EGL_TRUE) {
c->onMakeCurrent(draw, read);
if (!cur_c) {
- mWakeCount++;
- mAttemptHibernation = false;
+ mHibernation.incWakeCount(HibernationMachine::STRONG);
}
}
} else {
@@ -360,8 +363,7 @@
disp.dpy, impl_draw, impl_read, impl_ctx);
if (result == EGL_TRUE) {
cur_c->onLooseCurrent();
- mWakeCount--;
- mAttemptHibernation = true;
+ mHibernation.decWakeCount(HibernationMachine::STRONG);
}
}
}
@@ -378,14 +380,26 @@
return result;
}
-bool egl_display_t::enter() {
- Mutex::Autolock _l(lock);
+// ----------------------------------------------------------------------------
+
+bool egl_display_t::HibernationMachine::incWakeCount(WakeRefStrength strength) {
+ Mutex::Autolock _l(mLock);
ALOGE_IF(mWakeCount < 0 || mWakeCount == INT32_MAX,
"Invalid WakeCount (%d) on enter\n", mWakeCount);
+
mWakeCount++;
+ if (strength == STRONG)
+ mAttemptHibernation = false;
+
if (CC_UNLIKELY(mHibernating)) {
ALOGV("Awakening\n");
egl_connection_t* const cnx = &gEGLImpl;
+
+ // These conditions should be guaranteed before entering hibernation;
+ // we don't want to get into a state where we can't wake up.
+ ALOGD_IF(!mDpyValid || !cnx->egl.eglAwakenProcessIMG,
+ "Invalid hibernation state, unable to awaken\n");
+
if (!cnx->egl.eglAwakenProcessIMG()) {
ALOGE("Failed to awaken EGL implementation\n");
return false;
@@ -395,13 +409,20 @@
return true;
}
-void egl_display_t::leave() {
- Mutex::Autolock _l(lock);
+void egl_display_t::HibernationMachine::decWakeCount(WakeRefStrength strength) {
+ Mutex::Autolock _l(mLock);
ALOGE_IF(mWakeCount <= 0, "Invalid WakeCount (%d) on leave\n", mWakeCount);
- if (--mWakeCount == 0 && CC_UNLIKELY(mAttemptHibernation)) {
+
+ mWakeCount--;
+ if (strength == STRONG)
+ mAttemptHibernation = true;
+
+ if (mWakeCount == 0 && CC_UNLIKELY(mAttemptHibernation)) {
egl_connection_t* const cnx = &gEGLImpl;
mAttemptHibernation = false;
- if (cnx->egl.eglHibernateProcessIMG && cnx->egl.eglAwakenProcessIMG) {
+ if (mDpyValid &&
+ cnx->egl.eglHibernateProcessIMG &&
+ cnx->egl.eglAwakenProcessIMG) {
ALOGV("Hibernating\n");
if (!cnx->egl.eglHibernateProcessIMG()) {
ALOGE("Failed to hibernate EGL implementation\n");
@@ -412,16 +433,9 @@
}
}
-void egl_display_t::onWindowSurfaceCreated() {
- Mutex::Autolock _l(lock);
- mWakeCount++;
- mAttemptHibernation = false;
-}
-
-void egl_display_t::onWindowSurfaceDestroyed() {
- Mutex::Autolock _l(lock);
- mWakeCount--;
- mAttemptHibernation = true;
+void egl_display_t::HibernationMachine::setDisplayValid(bool valid) {
+ Mutex::Autolock _l(mLock);
+ mDpyValid = valid;
}
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 28607da..412568b 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -77,8 +77,12 @@
// proper hibernate/wakeup sequencing. If a surface destruction triggers
// hibernation, hibernation will be delayed at least until the calling
// thread's egl_display_ptr is destroyed.
- void onWindowSurfaceCreated();
- void onWindowSurfaceDestroyed();
+ void onWindowSurfaceCreated() {
+ mHibernation.incWakeCount(HibernationMachine::STRONG);
+ }
+ void onWindowSurfaceDestroyed() {
+ mHibernation.decWakeCount(HibernationMachine::STRONG);
+ }
static egl_display_t* get(EGLDisplay dpy);
static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp);
@@ -123,8 +127,8 @@
private:
friend class egl_display_ptr;
- bool enter();
- void leave();
+ bool enter() { return mHibernation.incWakeCount(HibernationMachine::WEAK); }
+ void leave() { return mHibernation.decWakeCount(HibernationMachine::WEAK); }
uint32_t refs;
mutable Mutex lock;
@@ -133,9 +137,41 @@
String8 mVersionString;
String8 mClientApiString;
String8 mExtensionString;
- int32_t mWakeCount;
- bool mHibernating;
- bool mAttemptHibernation;
+
+ // HibernationMachine uses its own internal mutex to protect its own data.
+ // The owning egl_display_t's lock may be but is not required to be held
+ // when calling HibernationMachine methods. As a result, nothing in this
+ // class may call back up to egl_display_t directly or indirectly.
+ class HibernationMachine {
+ public:
+ // STRONG refs cancel (inc) or initiate (dec) a hibernation attempt
+ // the next time the wakecount reaches zero. WEAK refs don't affect
+ // whether a hibernation attempt will be made. Use STRONG refs only
+ // for infrequent/heavy changes that are likely to indicate the
+ // EGLDisplay is entering or leaving a long-term idle state.
+ enum WakeRefStrength {
+ WEAK = 0,
+ STRONG = 1,
+ };
+
+ HibernationMachine(): mWakeCount(0), mHibernating(false),
+ mAttemptHibernation(false), mDpyValid(false)
+ {}
+ ~HibernationMachine() {}
+
+ bool incWakeCount(WakeRefStrength strenth);
+ void decWakeCount(WakeRefStrength strenth);
+
+ void setDisplayValid(bool valid);
+
+ private:
+ Mutex mLock;
+ int32_t mWakeCount;
+ bool mHibernating;
+ bool mAttemptHibernation;
+ bool mDpyValid;
+ };
+ HibernationMachine mHibernation;
};
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index c46e630..48651b6 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -280,12 +280,6 @@
EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
}
- if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
- if (dummy == EGL_BUFFER_PRESERVED) {
- mFlags |= BUFFER_PRESERVED;
- }
- }
-
/*
* Create our OpenGL ES context
*/
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 84a3eff..f1dee91 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -51,7 +51,6 @@
enum {
COPY_BITS_EXTENSION = 0x00000008,
- BUFFER_PRESERVED = 0x00010000,
PARTIAL_UPDATES = 0x00020000, // video driver feature
SLOW_CONFIG = 0x00040000, // software
SWAP_RECTANGLE = 0x00080000,
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index e764001..694ecde 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), mInOverlay(false),
+ mNeedsFiltering(false),
mOrientation(0),
mPlaneOrientation(0),
mTransactionFlags(0),
@@ -231,7 +231,9 @@
const uint32_t hw_h = hw.getHeight();
uint32_t w = s.w;
- uint32_t h = s.h;
+ uint32_t h = s.h;
+
+ mNumVertices = 4;
tr.transform(mVertices[0], 0, 0);
tr.transform(mVertices[1], 0, h);
tr.transform(mVertices[2], w, h);
@@ -268,27 +270,6 @@
const Transform& planeTransform, Region& outDirtyRegion) {
}
-void LayerBase::drawRegion(const Region& reg) const
-{
- Region::const_iterator it = reg.begin();
- Region::const_iterator const end = reg.end();
- if (it != end) {
- Rect r;
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const int32_t fbWidth = hw.getWidth();
- const int32_t fbHeight = hw.getHeight();
- const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 },
- { fbWidth, fbHeight }, { 0, fbHeight } };
- glVertexPointer(2, GL_SHORT, 0, vertices);
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- }
-}
-
void LayerBase::setGeometry(hwc_layer_t* hwcl)
{
hwcl->compositionType = HWC_FRAMEBUFFER;
@@ -333,14 +314,6 @@
hwcl->handle = NULL;
}
-void LayerBase::setOverlay(bool inOverlay) {
- mInOverlay = inOverlay;
-}
-
-bool LayerBase::isOverlay() const {
- return mInOverlay;
-}
-
void LayerBase::setFiltering(bool filtering)
{
mFiltering = filtering;
@@ -353,9 +326,6 @@
void LayerBase::draw(const Region& clip) const
{
- // reset GL state
- glEnable(GL_SCISSOR_TEST);
-
onDraw(clip);
}
@@ -379,16 +349,8 @@
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- Region::const_iterator it = clip.begin();
- Region::const_iterator const end = clip.end();
- glEnable(GL_SCISSOR_TEST);
glVertexPointer(2, GL_FLOAT, 0, mVertices);
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
}
void LayerBase::clearWithOpenGL(const Region& clip) const
@@ -442,15 +404,8 @@
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, mVertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
- Region::const_iterator it = clip.begin();
- Region::const_iterator const end = clip.end();
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_BLEND);
}
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index cd6efdd..d123d9b 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -100,7 +100,6 @@
uint32_t setTransactionFlags(uint32_t flags);
Rect visibleBounds() const;
- void drawRegion(const Region& reg) const;
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
virtual sp<Layer> getLayer() const { return 0; }
@@ -109,8 +108,6 @@
virtual void setGeometry(hwc_layer_t* hwcl);
virtual void setPerFrameData(hwc_layer_t* hwcl);
- void setOverlay(bool inOverlay);
- bool isOverlay() const;
/**
@@ -230,14 +227,15 @@
int32_t getOrientation() const { return mOrientation; }
int32_t getPlaneOrientation() const { return mPlaneOrientation; }
-
+
+ void clearWithOpenGL(const Region& clip) const;
+
protected:
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
GLclampf b, GLclampf alpha) const;
- void clearWithOpenGL(const Region& clip) const;
void drawWithOpenGL(const Region& clip) const;
void setFiltering(bool filtering);
@@ -255,17 +253,13 @@
// 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;
int32_t mPlaneOrientation;
Transform mTransform;
GLfloat mVertices[4][2];
+ size_t mNumVertices;
Rect mTransformedBounds;
// these are protected by an external lock
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index e665d7a..96a310f 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -43,9 +43,7 @@
void LayerDim::onDraw(const Region& clip) const
{
const State& s(drawingState());
- Region::const_iterator it = clip.begin();
- Region::const_iterator const end = clip.end();
- if (s.alpha>0 && (it != end)) {
+ if (s.alpha>0) {
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const GLfloat alpha = s.alpha/255.0f;
const uint32_t fbHeight = hw.getHeight();
@@ -62,13 +60,8 @@
glColor4f(0, 0, 0, alpha);
glVertexPointer(2, GL_FLOAT, 0, mVertices);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
glDisable(GL_BLEND);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index c7cf46e..b42353c 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -70,8 +70,6 @@
glBindTexture(GL_TEXTURE_2D, mTextureName);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
mTexCoords[0] = 0; mTexCoords[1] = v;
mTexCoords[2] = 0; mTexCoords[3] = 0;
mTexCoords[4] = u; mTexCoords[5] = 0;
@@ -111,9 +109,7 @@
void LayerScreenshot::onDraw(const Region& clip) const
{
const State& s(drawingState());
- Region::const_iterator it = clip.begin();
- Region::const_iterator const end = clip.end();
- if (s.alpha>0 && (it != end)) {
+ if (s.alpha>0) {
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const GLfloat alpha = s.alpha/255.0f;
const uint32_t fbHeight = hw.getHeight();
@@ -139,13 +135,7 @@
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
glVertexPointer(2, GL_FLOAT, 0, mVertices);
-
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
+ glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fb0c305..0d4d2b9 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");
}
@@ -265,7 +260,6 @@
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glEnableClientState(GL_VERTEX_ARRAY);
- glEnable(GL_SCISSOR_TEST);
glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);
@@ -834,22 +828,11 @@
glLoadIdentity();
uint32_t flags = hw.getFlags();
- if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
- (flags & DisplayHardware::BUFFER_PRESERVED))
- {
+ if (flags & DisplayHardware::SWAP_RECTANGLE) {
// we can redraw only what's dirty, but since SWAP_RECTANGLE only
// takes a rectangle, we must make sure to update that whole
// rectangle in that case
- if (flags & DisplayHardware::SWAP_RECTANGLE) {
- // TODO: we really should be able to pass a region to
- // SWAP_RECTANGLE so that we don't have to redraw all this.
- mDirtyRegion.set(mSwapRegion.bounds());
- } else {
- // in the BUFFER_PRESERVED case, obviously, we can update only
- // what's needed and nothing more.
- // NOTE: this is NOT a common case, as preserving the backbuffer
- // is costly and usually involves copying the whole update back.
- }
+ mDirtyRegion.set(mSwapRegion.bounds());
} else {
if (flags & DisplayHardware::PARTIAL_UPDATES) {
// We need to redraw the rectangle that will be updated
@@ -864,7 +847,7 @@
}
}
- setupHardwareComposer(mDirtyRegion);
+ setupHardwareComposer();
composeSurfaces(mDirtyRegion);
// update the swap region and clear the dirty region
@@ -872,7 +855,7 @@
mDirtyRegion.clear();
}
-void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
+void SurfaceFlinger::setupHardwareComposer()
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
@@ -901,120 +884,59 @@
const sp<LayerBase>& layer(layers[i]);
layer->setPerFrameData(&cur[i]);
}
- const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
-
- if (err == NO_ERROR) {
- // 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 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.
- //
- // Note also that there is a special case when switching from
- // "no layers in FB" to "some layers in FB", where we need to redraw
- // the entire FB, since some areas might contain uninitialized
- // data.
- //
- // Also we want to make sure to not clear areas that belong to
- // layers above that won't redraw (we would just be erasing them),
- // that is, we can't erase anything outside the dirty region.
-
- Region transparent;
-
- if (!fbLayerCount && hwc.getLayerCount(HWC_FRAMEBUFFER)) {
- transparent.set(hw.getBounds());
- dirtyInOut = transparent;
- } else {
- for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer(layers[i]);
- if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
- transparent.orSelf(layer->visibleRegionScreen);
- }
- bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER);
- 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.
- dirtyInOut.orSelf(layer->visibleRegionScreen);
- }
- layer->setOverlay(isOverlay);
- }
- // don't erase stuff outside the dirty region
- transparent.andSelf(dirtyInOut);
- }
-
- /*
- * clear the area of the FB that need to be transparent
- */
- 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);
- }
- }
- }
}
void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
+ hwc_layer_t* const cur(hwc.getLayers());
const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
- if (CC_UNLIKELY(fbLayerCount && !mWormholeRegion.isEmpty())) {
- // should never happen unless the window manager has a bug
- // draw something...
- drawWormhole();
- }
+ if (!cur || fbLayerCount) {
+ // Never touch the framebuffer if we don't have any framebuffer layers
- /*
- * and then, render the layers targeted at the framebuffer
- */
-
- hwc_layer_t* const cur(hwc.getLayers());
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- size_t count = layers.size();
-
-
- // FIXME: workaround for b/6020860
- if (hw.getFlags() & DisplayHardware::BUFFER_PRESERVED) {
- for (size_t i=0 ; i<count ; i++) {
- if (cur && (cur[i].compositionType == HWC_FRAMEBUFFER)) {
- glEnable(GL_SCISSOR_TEST);
- glScissor(0,0,0,0);
- glClear(GL_COLOR_BUFFER_BIT);
- break;
+ 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();
}
}
- }
- // FIXME: bug6020860 for b/6020860
+ /*
+ * and then, render the layers targeted at the framebuffer
+ */
- for (size_t i=0 ; i<count ; i++) {
- if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
- continue;
- }
- const sp<LayerBase>& layer(layers[i]);
- const Region clip(dirty.intersect(layer->visibleRegionScreen));
- if (!clip.isEmpty()) {
- layer->draw(clip);
+ const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ const size_t count = layers.size();
+
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(layers[i]);
+ const Region clip(dirty.intersect(layer->visibleRegionScreen));
+ if (!clip.isEmpty()) {
+ 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;
+ }
+ // render the layer
+ layer->draw(clip);
+ }
}
}
}
@@ -1028,8 +950,7 @@
return;
}
- if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
- (flags & DisplayHardware::BUFFER_PRESERVED))) {
+ if (!(flags & DisplayHardware::SWAP_RECTANGLE)) {
const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
mDirtyRegion.bounds() : hw.bounds());
composeSurfaces(repaint);
@@ -1066,8 +987,6 @@
if (mDebugRegion > 1)
usleep(mDebugRegion * 1000);
-
- glEnable(GL_SCISSOR_TEST);
}
void SurfaceFlinger::drawWormhole() const
@@ -1076,51 +995,26 @@
if (region.isEmpty())
return;
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const int32_t width = hw.getWidth();
- const int32_t height = hw.getHeight();
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glColor4f(0,0,0,0);
- if (CC_LIKELY(!mDebugBackground)) {
- glClearColor(0,0,0,0);
- Region::const_iterator it = region.begin();
- Region::const_iterator const end = region.end();
- 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);
- }
- } else {
- const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
- { width, height }, { 0, height } };
- const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
-
- glVertexPointer(2, GL_SHORT, 0, vertices);
- glTexCoordPointer(2, GL_SHORT, 0, tcoords);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
-
- glDisable(GL_BLEND);
-
- glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
- Region::const_iterator it = region.begin();
- Region::const_iterator const end = region.end();
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = height - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisable(GL_TEXTURE_2D);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
+ GLfloat vertices[4][2];
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ Region::const_iterator it = region.begin();
+ Region::const_iterator const end = region.end();
+ while (it != end) {
+ const Rect& r = *it++;
+ vertices[0][0] = r.left;
+ vertices[0][1] = r.top;
+ vertices[1][0] = r.right;
+ vertices[1][1] = r.top;
+ vertices[2][0] = r.right;
+ vertices[2][1] = r.bottom;
+ vertices[3][0] = r.left;
+ vertices[3][1] = r.bottom;
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
}
@@ -1807,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;
@@ -1839,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: {
@@ -1903,6 +1793,8 @@
GLuint name, tname;
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
if (glGetError() != GL_NO_ERROR) {
@@ -1925,7 +1817,6 @@
glDisable(GL_SCISSOR_TEST);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
- glEnable(GL_SCISSOR_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
@@ -2110,11 +2001,11 @@
}
glColorMask(1,1,1,1);
- glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
return NO_ERROR;
}
@@ -2253,11 +2144,11 @@
}
glColorMask(1,1,1,1);
- glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
return NO_ERROR;
}
@@ -2287,7 +2178,6 @@
glClearColor(0,0,0,1);
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
- glEnable(GL_SCISSOR_TEST);
hw.flip( Region(hw.bounds()) );
return NO_ERROR;
@@ -2425,7 +2315,6 @@
// invert everything, b/c glReadPixel() below will invert the FB
glViewport(0, 0, sw, sh);
glScissor(0, 0, sw, sh);
- glEnable(GL_SCISSOR_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -2478,7 +2367,7 @@
result = NO_MEMORY;
}
}
- glEnable(GL_SCISSOR_TEST);
+ glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, hw_w, hw_h);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 46bbab2..d9c2033 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -318,7 +318,7 @@
void handleWorkList();
void handleRepaint();
void postFramebuffer();
- void setupHardwareComposer(Region& dirtyInOut);
+ void setupHardwareComposer();
void composeSurfaces(const Region& dirty);
@@ -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;
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index d7fd39e..2b647bb 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -40,10 +40,6 @@
outWidth, outHeight, outTransform);
if (err == NO_ERROR) {
switch(api) {
- case NATIVE_WINDOW_API_CPU:
- // SurfaceTextureClient supports only 2 buffers for CPU connections
- this->setBufferCountServer(2);
- break;
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
// Camera preview and videos are rate-limited on the producer