summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gui/DisplayEventReceiver.h14
-rw-r--r--include/gui/IDisplayEventConnection.h18
-rw-r--r--libs/gui/DisplayEventReceiver.cpp20
-rw-r--r--libs/gui/IDisplayEventConnection.cpp25
-rw-r--r--opengl/libs/GLES_trace/gltrace.proto9
-rw-r--r--opengl/libs/GLES_trace/src/gltrace.pb.cpp270
-rw-r--r--opengl/libs/GLES_trace/src/gltrace.pb.h211
-rw-r--r--opengl/libs/GLES_trace/src/gltrace_fixup.cpp18
-rw-r--r--services/surfaceflinger/DisplayEventConnection.cpp19
-rw-r--r--services/surfaceflinger/DisplayEventConnection.h8
-rw-r--r--services/surfaceflinger/EventThread.cpp145
-rw-r--r--services/surfaceflinger/EventThread.h27
-rw-r--r--services/surfaceflinger/MessageQueue.cpp14
-rw-r--r--services/surfaceflinger/MessageQueue.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp18
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h4
16 files changed, 757 insertions, 64 deletions
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index 8d07c0e492..dccc1643c9 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -94,6 +94,20 @@ public:
*/
ssize_t getEvents(Event* events, size_t count);
+ /*
+ * setVsyncRate() sets the Event::VSync delivery rate. A value of
+ * 1 returns every Event::VSync. A value of 2 returns every other event,
+ * etc... a value of 0 returns no event unless requestNextVsync() has
+ * been called.
+ */
+ status_t setVsyncRate(uint32_t count);
+
+ /*
+ * requestNextVsync() schedules the next Event::VSync. It has no effect
+ * if the vsync rate is > 0.
+ */
+ status_t requestNextVsync();
+
private:
sp<IDisplayEventConnection> mEventConnection;
sp<BitTube> mDataChannel;
diff --git a/include/gui/IDisplayEventConnection.h b/include/gui/IDisplayEventConnection.h
index 8728bb5ed7..86247de62b 100644
--- a/include/gui/IDisplayEventConnection.h
+++ b/include/gui/IDisplayEventConnection.h
@@ -33,9 +33,27 @@ class BitTube;
class IDisplayEventConnection : public IInterface
{
public:
+
DECLARE_META_INTERFACE(DisplayEventConnection);
+ /*
+ * getDataChannel() returns a BitTube where to receive the events from
+ */
virtual sp<BitTube> getDataChannel() const = 0;
+
+ /*
+ * setVsyncRate() sets the vsync event delivery rate. A value of
+ * 1 returns every vsync events. A value of 2 returns every other events,
+ * etc... a value of 0 returns no event unless requestNextVsync() has
+ * been called.
+ */
+ virtual void setVsyncRate(uint32_t count) = 0;
+
+ /*
+ * requestNextVsync() schedules the next vsync event. It has no effect
+ * if the vsync rate is > 0.
+ */
+ virtual void requestNextVsync() = 0; // asynchronous
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 3b29a113e4..fee1febb9b 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -58,6 +58,26 @@ int DisplayEventReceiver::getFd() const {
return mDataChannel->getFd();
}
+status_t DisplayEventReceiver::setVsyncRate(uint32_t count) {
+ if (int32_t(count) < 0)
+ return BAD_VALUE;
+
+ if (mEventConnection != NULL) {
+ mEventConnection->setVsyncRate(count);
+ return NO_ERROR;
+ }
+ return NO_INIT;
+}
+
+status_t DisplayEventReceiver::requestNextVsync() {
+ if (mEventConnection != NULL) {
+ mEventConnection->requestNextVsync();
+ return NO_ERROR;
+ }
+ return NO_INIT;
+}
+
+
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
size_t count) {
ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index 44127fb4ac..887d176b44 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -32,6 +32,8 @@ namespace android {
enum {
GET_DATA_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
+ SET_VSYNC_RATE,
+ REQUEST_NEXT_VSYNC
};
class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection>
@@ -49,6 +51,19 @@ public:
remote()->transact(GET_DATA_CHANNEL, data, &reply);
return new BitTube(reply);
}
+
+ virtual void setVsyncRate(uint32_t count) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
+ data.writeInt32(count);
+ remote()->transact(SET_VSYNC_RATE, data, &reply);
+ }
+
+ virtual void requestNextVsync() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
+ remote()->transact(REQUEST_NEXT_VSYNC, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection");
@@ -65,6 +80,16 @@ status_t BnDisplayEventConnection::onTransact(
channel->writeToParcel(reply);
return NO_ERROR;
} break;
+ case SET_VSYNC_RATE: {
+ CHECK_INTERFACE(IDisplayEventConnection, data, reply);
+ setVsyncRate(data.readInt32());
+ return NO_ERROR;
+ } break;
+ case REQUEST_NEXT_VSYNC: {
+ CHECK_INTERFACE(IDisplayEventConnection, data, reply);
+ requestNextVsync();
+ return NO_ERROR;
+ } break;
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/opengl/libs/GLES_trace/gltrace.proto b/opengl/libs/GLES_trace/gltrace.proto
index 59f80e3aba..12d8e7c0e8 100644
--- a/opengl/libs/GLES_trace/gltrace.proto
+++ b/opengl/libs/GLES_trace/gltrace.proto
@@ -459,7 +459,7 @@ message GLMessage {
BYTE = 3; // GLbyte, GLubyte
INT = 4; // GLbitfield, GLshort, GLint, GLsizei, GLushort, GLuint, GLfixed
FLOAT = 5; // GLfloat, GLclampf
- BOOL = 6; // GLboolean
+ BOOL = 6; // GLboolean
ENUM = 7; // GLenum
};
@@ -473,9 +473,16 @@ message GLMessage {
repeated bool boolValue = 7;
}
+ message FrameBuffer {
+ required int32 width = 1;
+ required int32 height = 2;
+ repeated bytes contents = 3;
+ }
+
required int32 context_id = 1; // GL context ID
required Function function = 2 [default = invalid]; // GL function called
repeated DataType args = 3; // GL function's arguments
optional DataType returnValue = 4; // GL function's return value
optional float duration = 5; // duration of GL call
+ optional FrameBuffer fb = 6; // contents of the framebuffer
};
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.cpp b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
index 160afbf4ce..6c1bb918ee 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
@@ -13,6 +13,7 @@ namespace gltrace {
void protobuf_ShutdownFile_gltrace_2eproto() {
delete GLMessage::default_instance_;
delete GLMessage_DataType::default_instance_;
+ delete GLMessage_FrameBuffer::default_instance_;
}
void protobuf_AddDesc_gltrace_2eproto() {
@@ -23,8 +24,10 @@ void protobuf_AddDesc_gltrace_2eproto() {
GLMessage::default_instance_ = new GLMessage();
GLMessage_DataType::default_instance_ = new GLMessage_DataType();
+ GLMessage_FrameBuffer::default_instance_ = new GLMessage_FrameBuffer();
GLMessage::default_instance_->InitAsDefaultInstance();
GLMessage_DataType::default_instance_->InitAsDefaultInstance();
+ GLMessage_FrameBuffer::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_gltrace_2eproto);
}
@@ -1306,11 +1309,238 @@ void GLMessage_DataType::Swap(GLMessage_DataType* other) {
// -------------------------------------------------------------------
#ifndef _MSC_VER
+const int GLMessage_FrameBuffer::kWidthFieldNumber;
+const int GLMessage_FrameBuffer::kHeightFieldNumber;
+const int GLMessage_FrameBuffer::kContentsFieldNumber;
+#endif // !_MSC_VER
+
+GLMessage_FrameBuffer::GLMessage_FrameBuffer()
+ : ::google::protobuf::MessageLite() {
+ SharedCtor();
+}
+
+void GLMessage_FrameBuffer::InitAsDefaultInstance() {
+}
+
+GLMessage_FrameBuffer::GLMessage_FrameBuffer(const GLMessage_FrameBuffer& from)
+ : ::google::protobuf::MessageLite() {
+ SharedCtor();
+ MergeFrom(from);
+}
+
+void GLMessage_FrameBuffer::SharedCtor() {
+ _cached_size_ = 0;
+ width_ = 0;
+ height_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GLMessage_FrameBuffer::~GLMessage_FrameBuffer() {
+ SharedDtor();
+}
+
+void GLMessage_FrameBuffer::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void GLMessage_FrameBuffer::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GLMessage_FrameBuffer& GLMessage_FrameBuffer::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_gltrace_2eproto(); return *default_instance_;
+}
+
+GLMessage_FrameBuffer* GLMessage_FrameBuffer::default_instance_ = NULL;
+
+GLMessage_FrameBuffer* GLMessage_FrameBuffer::New() const {
+ return new GLMessage_FrameBuffer;
+}
+
+void GLMessage_FrameBuffer::Clear() {
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ width_ = 0;
+ height_ = 0;
+ }
+ contents_.Clear();
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+bool GLMessage_FrameBuffer::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::google::protobuf::uint32 tag;
+ while ((tag = input->ReadTag()) != 0) {
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // required int32 width = 1;
+ case 1: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &width_)));
+ _set_bit(0);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(16)) goto parse_height;
+ break;
+ }
+
+ // required int32 height = 2;
+ case 2: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_height:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &height_)));
+ _set_bit(1);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(26)) goto parse_contents;
+ break;
+ }
+
+ // repeated bytes contents = 3;
+ case 3: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_contents:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+ input, this->add_contents()));
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(26)) goto parse_contents;
+ if (input->ExpectAtEnd()) return true;
+ break;
+ }
+
+ default: {
+ handle_uninterpreted:
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ return true;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+ return true;
+#undef DO_
+}
+
+void GLMessage_FrameBuffer::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // required int32 width = 1;
+ if (_has_bit(0)) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->width(), output);
+ }
+
+ // required int32 height = 2;
+ if (_has_bit(1)) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->height(), output);
+ }
+
+ // repeated bytes contents = 3;
+ for (int i = 0; i < this->contents_size(); i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteBytes(
+ 3, this->contents(i), output);
+ }
+
+}
+
+int GLMessage_FrameBuffer::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ // required int32 width = 1;
+ if (has_width()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->width());
+ }
+
+ // required int32 height = 2;
+ if (has_height()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->height());
+ }
+
+ }
+ // repeated bytes contents = 3;
+ total_size += 1 * this->contents_size();
+ for (int i = 0; i < this->contents_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::BytesSize(
+ this->contents(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void GLMessage_FrameBuffer::CheckTypeAndMergeFrom(
+ const ::google::protobuf::MessageLite& from) {
+ MergeFrom(*::google::protobuf::down_cast<const GLMessage_FrameBuffer*>(&from));
+}
+
+void GLMessage_FrameBuffer::MergeFrom(const GLMessage_FrameBuffer& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ contents_.MergeFrom(from.contents_);
+ if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (from._has_bit(0)) {
+ set_width(from.width());
+ }
+ if (from._has_bit(1)) {
+ set_height(from.height());
+ }
+ }
+}
+
+void GLMessage_FrameBuffer::CopyFrom(const GLMessage_FrameBuffer& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool GLMessage_FrameBuffer::IsInitialized() const {
+ if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+ return true;
+}
+
+void GLMessage_FrameBuffer::Swap(GLMessage_FrameBuffer* other) {
+ if (other != this) {
+ std::swap(width_, other->width_);
+ std::swap(height_, other->height_);
+ contents_.Swap(&other->contents_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
+::std::string GLMessage_FrameBuffer::GetTypeName() const {
+ return "android.gltrace.GLMessage.FrameBuffer";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
const int GLMessage::kContextIdFieldNumber;
const int GLMessage::kFunctionFieldNumber;
const int GLMessage::kArgsFieldNumber;
const int GLMessage::kReturnValueFieldNumber;
const int GLMessage::kDurationFieldNumber;
+const int GLMessage::kFbFieldNumber;
#endif // !_MSC_VER
GLMessage::GLMessage()
@@ -1320,6 +1550,7 @@ GLMessage::GLMessage()
void GLMessage::InitAsDefaultInstance() {
returnvalue_ = const_cast< ::android::gltrace::GLMessage_DataType*>(&::android::gltrace::GLMessage_DataType::default_instance());
+ fb_ = const_cast< ::android::gltrace::GLMessage_FrameBuffer*>(&::android::gltrace::GLMessage_FrameBuffer::default_instance());
}
GLMessage::GLMessage(const GLMessage& from)
@@ -1334,6 +1565,7 @@ void GLMessage::SharedCtor() {
function_ = 3000;
returnvalue_ = NULL;
duration_ = 0;
+ fb_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -1344,6 +1576,7 @@ GLMessage::~GLMessage() {
void GLMessage::SharedDtor() {
if (this != default_instance_) {
delete returnvalue_;
+ delete fb_;
}
}
@@ -1370,6 +1603,9 @@ void GLMessage::Clear() {
if (returnvalue_ != NULL) returnvalue_->::android::gltrace::GLMessage_DataType::Clear();
}
duration_ = 0;
+ if (_has_bit(5)) {
+ if (fb_ != NULL) fb_->::android::gltrace::GLMessage_FrameBuffer::Clear();
+ }
}
args_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -1456,6 +1692,20 @@ bool GLMessage::MergePartialFromCodedStream(
} else {
goto handle_uninterpreted;
}
+ if (input->ExpectTag(50)) goto parse_fb;
+ break;
+ }
+
+ // optional .android.gltrace.GLMessage.FrameBuffer fb = 6;
+ case 6: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_fb:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_fb()));
+ } else {
+ goto handle_uninterpreted;
+ }
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1505,6 +1755,12 @@ void GLMessage::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteFloat(5, this->duration(), output);
}
+ // optional .android.gltrace.GLMessage.FrameBuffer fb = 6;
+ if (_has_bit(5)) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessage(
+ 6, this->fb(), output);
+ }
+
}
int GLMessage::ByteSize() const {
@@ -1536,6 +1792,13 @@ int GLMessage::ByteSize() const {
total_size += 1 + 4;
}
+ // optional .android.gltrace.GLMessage.FrameBuffer fb = 6;
+ if (has_fb()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->fb());
+ }
+
}
// repeated .android.gltrace.GLMessage.DataType args = 3;
total_size += 1 * this->args_size();
@@ -1572,6 +1835,9 @@ void GLMessage::MergeFrom(const GLMessage& from) {
if (from._has_bit(4)) {
set_duration(from.duration());
}
+ if (from._has_bit(5)) {
+ mutable_fb()->::android::gltrace::GLMessage_FrameBuffer::MergeFrom(from.fb());
+ }
}
}
@@ -1590,6 +1856,9 @@ bool GLMessage::IsInitialized() const {
if (has_returnvalue()) {
if (!this->returnvalue().IsInitialized()) return false;
}
+ if (has_fb()) {
+ if (!this->fb().IsInitialized()) return false;
+ }
return true;
}
@@ -1600,6 +1869,7 @@ void GLMessage::Swap(GLMessage* other) {
args_.Swap(&other->args_);
std::swap(returnvalue_, other->returnvalue_);
std::swap(duration_, other->duration_);
+ std::swap(fb_, other->fb_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
std::swap(_cached_size_, other->_cached_size_);
}
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.h b/opengl/libs/GLES_trace/src/gltrace.pb.h
index be5ca2a74f..c39e1b230c 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.h
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.h
@@ -34,6 +34,7 @@ void protobuf_ShutdownFile_gltrace_2eproto();
class GLMessage;
class GLMessage_DataType;
+class GLMessage_FrameBuffer;
enum GLMessage_DataType_Type {
GLMessage_DataType_Type_VOID = 1,
@@ -658,6 +659,108 @@ class GLMessage_DataType : public ::google::protobuf::MessageLite {
};
// -------------------------------------------------------------------
+class GLMessage_FrameBuffer : public ::google::protobuf::MessageLite {
+ public:
+ GLMessage_FrameBuffer();
+ virtual ~GLMessage_FrameBuffer();
+
+ GLMessage_FrameBuffer(const GLMessage_FrameBuffer& from);
+
+ inline GLMessage_FrameBuffer& operator=(const GLMessage_FrameBuffer& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const GLMessage_FrameBuffer& default_instance();
+
+ void Swap(GLMessage_FrameBuffer* other);
+
+ // implements Message ----------------------------------------------
+
+ GLMessage_FrameBuffer* New() const;
+ void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+ void CopyFrom(const GLMessage_FrameBuffer& from);
+ void MergeFrom(const GLMessage_FrameBuffer& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ public:
+
+ ::std::string GetTypeName() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // required int32 width = 1;
+ inline bool has_width() const;
+ inline void clear_width();
+ static const int kWidthFieldNumber = 1;
+ inline ::google::protobuf::int32 width() const;
+ inline void set_width(::google::protobuf::int32 value);
+
+ // required int32 height = 2;
+ inline bool has_height() const;
+ inline void clear_height();
+ static const int kHeightFieldNumber = 2;
+ inline ::google::protobuf::int32 height() const;
+ inline void set_height(::google::protobuf::int32 value);
+
+ // repeated bytes contents = 3;
+ inline int contents_size() const;
+ inline void clear_contents();
+ static const int kContentsFieldNumber = 3;
+ inline const ::std::string& contents(int index) const;
+ inline ::std::string* mutable_contents(int index);
+ inline void set_contents(int index, const ::std::string& value);
+ inline void set_contents(int index, const char* value);
+ inline void set_contents(int index, const void* value, size_t size);
+ inline ::std::string* add_contents();
+ inline void add_contents(const ::std::string& value);
+ inline void add_contents(const char* value);
+ inline void add_contents(const void* value, size_t size);
+ inline const ::google::protobuf::RepeatedPtrField< ::std::string>& contents() const;
+ inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_contents();
+
+ // @@protoc_insertion_point(class_scope:android.gltrace.GLMessage.FrameBuffer)
+ private:
+ mutable int _cached_size_;
+
+ ::google::protobuf::int32 width_;
+ ::google::protobuf::int32 height_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> contents_;
+ friend void protobuf_AddDesc_gltrace_2eproto();
+ friend void protobuf_AssignDesc_gltrace_2eproto();
+ friend void protobuf_ShutdownFile_gltrace_2eproto();
+
+ ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+
+ // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+ inline bool _has_bit(int index) const {
+ return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+ }
+ inline void _set_bit(int index) {
+ _has_bits_[index / 32] |= (1u << (index % 32));
+ }
+ inline void _clear_bit(int index) {
+ _has_bits_[index / 32] &= ~(1u << (index % 32));
+ }
+
+ void InitAsDefaultInstance();
+ static GLMessage_FrameBuffer* default_instance_;
+};
+// -------------------------------------------------------------------
+
class GLMessage : public ::google::protobuf::MessageLite {
public:
GLMessage();
@@ -700,6 +803,7 @@ class GLMessage : public ::google::protobuf::MessageLite {
// nested types ----------------------------------------------------
typedef GLMessage_DataType DataType;
+ typedef GLMessage_FrameBuffer FrameBuffer;
typedef GLMessage_Function Function;
static const Function glActiveTexture = GLMessage_Function_glActiveTexture;
@@ -1178,6 +1282,13 @@ class GLMessage : public ::google::protobuf::MessageLite {
inline float duration() const;
inline void set_duration(float value);
+ // optional .android.gltrace.GLMessage.FrameBuffer fb = 6;
+ inline bool has_fb() const;
+ inline void clear_fb();
+ static const int kFbFieldNumber = 6;
+ inline const ::android::gltrace::GLMessage_FrameBuffer& fb() const;
+ inline ::android::gltrace::GLMessage_FrameBuffer* mutable_fb();
+
// @@protoc_insertion_point(class_scope:android.gltrace.GLMessage)
private:
mutable int _cached_size_;
@@ -1187,11 +1298,12 @@ class GLMessage : public ::google::protobuf::MessageLite {
::google::protobuf::RepeatedPtrField< ::android::gltrace::GLMessage_DataType > args_;
::android::gltrace::GLMessage_DataType* returnvalue_;
float duration_;
+ ::android::gltrace::GLMessage_FrameBuffer* fb_;
friend void protobuf_AddDesc_gltrace_2eproto();
friend void protobuf_AssignDesc_gltrace_2eproto();
friend void protobuf_ShutdownFile_gltrace_2eproto();
- ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
+ ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
@@ -1412,6 +1524,86 @@ GLMessage_DataType::mutable_boolvalue() {
// -------------------------------------------------------------------
+// GLMessage_FrameBuffer
+
+// required int32 width = 1;
+inline bool GLMessage_FrameBuffer::has_width() const {
+ return _has_bit(0);
+}
+inline void GLMessage_FrameBuffer::clear_width() {
+ width_ = 0;
+ _clear_bit(0);
+}
+inline ::google::protobuf::int32 GLMessage_FrameBuffer::width() const {
+ return width_;
+}
+inline void GLMessage_FrameBuffer::set_width(::google::protobuf::int32 value) {
+ _set_bit(0);
+ width_ = value;
+}
+
+// required int32 height = 2;
+inline bool GLMessage_FrameBuffer::has_height() const {
+ return _has_bit(1);
+}
+inline void GLMessage_FrameBuffer::clear_height() {
+ height_ = 0;
+ _clear_bit(1);
+}
+inline ::google::protobuf::int32 GLMessage_FrameBuffer::height() const {
+ return height_;
+}
+inline void GLMessage_FrameBuffer::set_height(::google::protobuf::int32 value) {
+ _set_bit(1);
+ height_ = value;
+}
+
+// repeated bytes contents = 3;
+inline int GLMessage_FrameBuffer::contents_size() const {
+ return contents_.size();
+}
+inline void GLMessage_FrameBuffer::clear_contents() {
+ contents_.Clear();
+}
+inline const ::std::string& GLMessage_FrameBuffer::contents(int index) const {
+ return contents_.Get(index);
+}
+inline ::std::string* GLMessage_FrameBuffer::mutable_contents(int index) {
+ return contents_.Mutable(index);
+}
+inline void GLMessage_FrameBuffer::set_contents(int index, const ::std::string& value) {
+ contents_.Mutable(index)->assign(value);
+}
+inline void GLMessage_FrameBuffer::set_contents(int index, const char* value) {
+ contents_.Mutable(index)->assign(value);
+}
+inline void GLMessage_FrameBuffer::set_contents(int index, const void* value, size_t size) {
+ contents_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* GLMessage_FrameBuffer::add_contents() {
+ return contents_.Add();
+}
+inline void GLMessage_FrameBuffer::add_contents(const ::std::string& value) {
+ contents_.Add()->assign(value);
+}
+inline void GLMessage_FrameBuffer::add_contents(const char* value) {
+ contents_.Add()->assign(value);
+}
+inline void GLMessage_FrameBuffer::add_contents(const void* value, size_t size) {
+ contents_.Add()->assign(reinterpret_cast<const char*>(value), size);
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+GLMessage_FrameBuffer::contents() const {
+ return contents_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+GLMessage_FrameBuffer::mutable_contents() {
+ return &contents_;
+}
+
+// -------------------------------------------------------------------
+
// GLMessage
// required int32 context_id = 1;
@@ -1505,6 +1697,23 @@ inline void GLMessage::set_duration(float value) {
duration_ = value;
}
+// optional .android.gltrace.GLMessage.FrameBuffer fb = 6;
+inline bool GLMessage::has_fb() const {
+ return _has_bit(5);
+}
+inline void GLMessage::clear_fb() {
+ if (fb_ != NULL) fb_->::android::gltrace::GLMessage_FrameBuffer::Clear();
+ _clear_bit(5);
+}
+inline const ::android::gltrace::GLMessage_FrameBuffer& GLMessage::fb() const {
+ return fb_ != NULL ? *fb_ : *default_instance_->fb_;
+}
+inline ::android::gltrace::GLMessage_FrameBuffer* GLMessage::mutable_fb() {
+ _set_bit(5);
+ if (fb_ == NULL) fb_ = new ::android::gltrace::GLMessage_FrameBuffer;
+ return fb_;
+}
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index 90021f4cb6..c5b04511a0 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -95,20 +95,16 @@ void fixup_glGetString(GLMessage *glmsg) {
}
}
-/* Add the contents of the framebuffer as an argument */
+/* Add the contents of the framebuffer to the protobuf message */
void fixup_addFBContents(GLMessage *glmsg) {
- GLMessage_DataType *arg_fb = glmsg->add_args(); /* Add the FB as the last argument */
- GLTraceContext *glContext = getGLTraceContext();
-
- void *fb;
+ void *fbcontents;
unsigned fbsize, fbwidth, fbheight;
- glContext->getCompressedFB(&fb, &fbsize, &fbwidth, &fbheight);
+ getGLTraceContext()->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight);
- arg_fb->set_isarray(true);
- arg_fb->set_type(GLMessage::DataType::BYTE);
- arg_fb->add_rawbytes(fb, fbsize);
- arg_fb->add_intvalue(fbwidth);
- arg_fb->add_intvalue(fbheight);
+ GLMessage_FrameBuffer *fb = glmsg->mutable_fb();
+ fb->set_width(fbwidth);
+ fb->set_height(fbheight);
+ fb->add_contents(fbcontents, fbsize);
}
void fixup_glTexImage2D(GLMessage *glmsg) {
diff --git a/services/surfaceflinger/DisplayEventConnection.cpp b/services/surfaceflinger/DisplayEventConnection.cpp
index a0aa9c019e..77ecbd280e 100644
--- a/services/surfaceflinger/DisplayEventConnection.cpp
+++ b/services/surfaceflinger/DisplayEventConnection.cpp
@@ -25,6 +25,7 @@
#include "SurfaceFlinger.h"
#include "DisplayEventConnection.h"
+#include "EventThread.h"
// ---------------------------------------------------------------------------
@@ -33,30 +34,38 @@ namespace android {
// ---------------------------------------------------------------------------
DisplayEventConnection::DisplayEventConnection(
- const sp<SurfaceFlinger>& flinger)
- : mFlinger(flinger), mChannel(new BitTube())
+ const sp<EventThread>& eventThread)
+ : mEventThread(eventThread), mChannel(new BitTube())
{
}
DisplayEventConnection::~DisplayEventConnection() {
- mFlinger->cleanupDisplayEventConnection(this);
+ mEventThread->unregisterDisplayEventConnection(this);
}
void DisplayEventConnection::onFirstRef() {
- // nothing to do here for now.
+ // NOTE: mEventThread doesn't hold a strong reference on us
+ mEventThread->registerDisplayEventConnection(this);
}
sp<BitTube> DisplayEventConnection::getDataChannel() const {
return mChannel;
}
+void DisplayEventConnection::setVsyncRate(uint32_t count) {
+ mEventThread->setVsyncRate(count, this);
+}
+
+void DisplayEventConnection::requestNextVsync() {
+ mEventThread->requestNextVsync(this);
+}
+
status_t DisplayEventConnection::postEvent(const DisplayEventReceiver::Event& event)
{
ssize_t size = mChannel->write(&event, sizeof(DisplayEventReceiver::Event));
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayEventConnection.h b/services/surfaceflinger/DisplayEventConnection.h
index 46cf64b4a2..cc3ee3659e 100644
--- a/services/surfaceflinger/DisplayEventConnection.h
+++ b/services/surfaceflinger/DisplayEventConnection.h
@@ -32,13 +32,13 @@ namespace android {
// ---------------------------------------------------------------------------
class BitTube;
-class SurfaceFlinger;
+class EventThread;
// ---------------------------------------------------------------------------
class DisplayEventConnection : public BnDisplayEventConnection {
public:
- DisplayEventConnection(const sp<SurfaceFlinger>& flinger);
+ DisplayEventConnection(const sp<EventThread>& flinger);
status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -46,8 +46,10 @@ private:
virtual ~DisplayEventConnection();
virtual void onFirstRef();
virtual sp<BitTube> getDataChannel() const;
+ virtual void setVsyncRate(uint32_t count);
+ virtual void requestNextVsync(); // asynchronous
- sp<SurfaceFlinger> const mFlinger;
+ sp<EventThread> const mEventThread;
sp<BitTube> const mChannel;
};
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index edb06ba21a..dc39f883eb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -47,7 +47,8 @@ void EventThread::onFirstRef() {
status_t EventThread::registerDisplayEventConnection(
const sp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
- mDisplayEventConnections.add(connection);
+ ConnectionInfo info;
+ mDisplayEventConnections.add(connection, info);
mCondition.signal();
return NO_ERROR;
}
@@ -55,43 +56,132 @@ status_t EventThread::registerDisplayEventConnection(
status_t EventThread::unregisterDisplayEventConnection(
const wp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
- mDisplayEventConnections.remove(connection);
+ mDisplayEventConnections.removeItem(connection);
mCondition.signal();
return NO_ERROR;
}
-bool EventThread::threadLoop() {
-
- nsecs_t timestamp;
+void EventThread::removeDisplayEventConnection(
+ const wp<DisplayEventConnection>& connection) {
Mutex::Autolock _l(mLock);
- do {
- // wait for listeners
- while (!mDisplayEventConnections.size()) {
- mCondition.wait(mLock);
- }
+ mDisplayEventConnections.removeItem(connection);
+}
- // wait for vsync
- mLock.unlock();
- timestamp = mHw.waitForVSync();
- mLock.lock();
+EventThread::ConnectionInfo* EventThread::getConnectionInfoLocked(
+ const wp<DisplayEventConnection>& connection) {
+ ssize_t index = mDisplayEventConnections.indexOfKey(connection);
+ if (index < 0) return NULL;
+ return &mDisplayEventConnections.editValueAt(index);
+}
- // make sure we still have some listeners
- } while (!mDisplayEventConnections.size());
+void EventThread::setVsyncRate(uint32_t count,
+ const wp<DisplayEventConnection>& connection) {
+ if (int32_t(count) >= 0) { // server must protect against bad params
+ Mutex::Autolock _l(mLock);
+ ConnectionInfo* info = getConnectionInfoLocked(connection);
+ if (info) {
+ info->count = (count == 0) ? -1 : count;
+ mCondition.signal();
+ }
+ }
+}
+void EventThread::requestNextVsync(
+ const wp<DisplayEventConnection>& connection) {
+ Mutex::Autolock _l(mLock);
+ ConnectionInfo* info = getConnectionInfoLocked(connection);
+ if (info) {
+ if (info->count < 0) {
+ info->count = 0;
+ }
+ mCondition.signal();
+ }
+}
- // dispatch vsync events to listeners...
- mDeliveredEvents++;
- const size_t count = mDisplayEventConnections.size();
+bool EventThread::threadLoop() {
+ nsecs_t timestamp;
DisplayEventReceiver::Event vsync;
- vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
- vsync.header.timestamp = timestamp;
- vsync.vsync.count = mDeliveredEvents;
+ KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > displayEventConnections;
+
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ do {
+ // wait for listeners
+ do {
+ bool waitForNextVsync = false;
+ size_t count = mDisplayEventConnections.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const ConnectionInfo& info(
+ mDisplayEventConnections.valueAt(i));
+ if (info.count >= 1) {
+ // continuous mode
+ waitForNextVsync = true;
+ } else {
+ // one-shot event
+ if (info.count >= -1) {
+ ConnectionInfo& info(
+ mDisplayEventConnections.editValueAt(i));
+ info.count--;
+ if (info.count == -1) {
+ // fired this time around
+ waitForNextVsync = true;
+ }
+ }
+ }
+ }
+
+ if (waitForNextVsync)
+ break;
+
+ mCondition.wait(mLock);
+ } while(true);
+
+ // wait for vsync
+ mLock.unlock();
+ timestamp = mHw.waitForVSync();
+ mLock.lock();
+ mDeliveredEvents++;
+
+ // make sure we still have some listeners
+ } while (!mDisplayEventConnections.size());
+
+ // dispatch vsync events to listeners...
+ vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+ vsync.header.timestamp = timestamp;
+ vsync.vsync.count = mDeliveredEvents;
+
+ // make a copy of our connection list, so we can
+ // dispatch events without holding mLock
+ displayEventConnections = mDisplayEventConnections;
+ }
+ const size_t count = displayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
- sp<DisplayEventConnection> conn(mDisplayEventConnections.itemAt(i).promote());
+ sp<DisplayEventConnection> conn(displayEventConnections.keyAt(i).promote());
// make sure the connection didn't die
if (conn != NULL) {
+
+ const ConnectionInfo& info(
+ displayEventConnections.valueAt(i));
+
+ if ((info.count > 1) && (mDeliveredEvents % info.count)) {
+ // continuous event, but not time to send this event yet
+ continue;
+ } else if (info.count < -1) {
+ // disabled event
+ continue;
+ } else if (info.count == 0) {
+ // impossible by construction. but we prefer to be safe.
+ continue;
+ }
+
+ // here, either:
+ // count = -1 : one-shot scheduled this time around
+ // count = 1 : continuous not rate-limited
+ // count > 1 : continuous, rate-limited
+ // Note: count == 0 is not possible by construction
+
status_t err = conn->postEvent(vsync);
if (err == -EAGAIN || err == -EWOULDBLOCK) {
// The destination doesn't accept events anymore, it's probably
@@ -103,11 +193,18 @@ bool EventThread::threadLoop() {
// handle any other error on the pipe as fatal. the only
// reasonable thing to do is to clean-up this connection.
// The most common error we'll get here is -EPIPE.
- mDisplayEventConnections.remove(conn);
+ removeDisplayEventConnection(displayEventConnections.keyAt(i));
}
+ } else {
+ // somehow the connection is dead, but we still have it in our list
+ // just clean the list.
+ removeDisplayEventConnection(displayEventConnections.keyAt(i));
}
}
+ // clear all our references without holding mLock
+ displayEventConnections.clear();
+
return true;
}
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 0482ab7528..35bd299a86 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -24,7 +24,7 @@
#include <utils/Errors.h>
#include <utils/threads.h>
-#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
#include "DisplayEventConnection.h"
@@ -51,6 +51,11 @@ public:
status_t unregisterDisplayEventConnection(
const wp<DisplayEventConnection>& connection);
+ void setVsyncRate(uint32_t count,
+ const wp<DisplayEventConnection>& connection);
+
+ void requestNextVsync(const wp<DisplayEventConnection>& connection);
+
void dump(String8& result, char* buffer, size_t SIZE) const;
private:
@@ -58,6 +63,22 @@ private:
virtual status_t readyToRun();
virtual void onFirstRef();
+ struct ConnectionInfo {
+ ConnectionInfo() : count(-1) { }
+
+ // count >= 1 : continuous event. count is the vsync rate
+ // count == 0 : one-shot event that has not fired
+ // count ==-1 : one-shot event that fired this round / disabled
+ // count ==-2 : one-shot event that fired the round before
+ int32_t count;
+ };
+
+ void removeDisplayEventConnection(
+ const wp<DisplayEventConnection>& connection);
+
+ ConnectionInfo* getConnectionInfoLocked(
+ const wp<DisplayEventConnection>& connection);
+
// constants
sp<SurfaceFlinger> mFlinger;
const DisplayHardware& mHw;
@@ -66,7 +87,9 @@ private:
mutable Condition mCondition;
// protected by mLock
- SortedVector<wp<DisplayEventConnection> > mDisplayEventConnections;
+ KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections;
+
+ // main thread only
size_t mDeliveredEvents;
};
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index fdde75c0a0..85845c922d 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -44,7 +44,7 @@ void MessageBase::handleMessage(const Message&) {
// ---------------------------------------------------------------------------
MessageQueue::MessageQueue()
- : mLooper(new Looper(true))
+ : mLooper(new Looper(true)), mWorkPending(0)
{
}
@@ -58,11 +58,11 @@ void MessageQueue::waitMessage() {
int32_t ret = mLooper->pollOnce(-1);
switch (ret) {
case ALOOPER_POLL_WAKE:
- // we got woken-up there is work to do in the main loop
- return;
-
case ALOOPER_POLL_CALLBACK:
- // callback was handled, loop again
+ // callback and/or wake
+ if (android_atomic_and(0, &mWorkPending)) {
+ return;
+ }
continue;
case ALOOPER_POLL_TIMEOUT:
@@ -94,7 +94,9 @@ status_t MessageQueue::postMessage(
}
status_t MessageQueue::invalidate() {
- mLooper->wake();
+ if (android_atomic_or(1, &mWorkPending) == 0) {
+ mLooper->wake();
+ }
return NO_ERROR;
}
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 775400f981..2317d81ab8 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -55,6 +55,7 @@ private:
class MessageQueue {
sp<Looper> mLooper;
+ volatile int32_t mWorkPending;
public:
MessageQueue();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 51c2be84f2..014c7e24af 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -389,16 +389,10 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
- sp<DisplayEventConnection> result(new DisplayEventConnection(this));
- mEventThread->registerDisplayEventConnection(result);
+ sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread));
return result;
}
-void SurfaceFlinger::cleanupDisplayEventConnection(
- const wp<DisplayEventConnection>& connection) {
- mEventThread->unregisterDisplayEventConnection(connection);
-}
-
// ----------------------------------------------------------------------------
#if 0
#pragma mark -
@@ -720,6 +714,14 @@ void SurfaceFlinger::computeVisibleRegions(
void SurfaceFlinger::commitTransaction()
{
+ if (!mLayersPendingRemoval.isEmpty()) {
+ // Notify removed layers now that they can't be drawn from
+ for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
+ mLayersPendingRemoval[i]->onRemoved();
+ }
+ mLayersPendingRemoval.clear();
+ }
+
mDrawingState = mCurrentState;
mTransationPending = false;
mTransactionCV.broadcast();
@@ -1172,7 +1174,7 @@ status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
mLayerPurgatory.add(layerBase);
}
- layerBase->onRemoved();
+ mLayersPendingRemoval.push(layerBase);
// it's possible that we don't find a layer, because it might
// have been destroyed already -- this is not technically an error
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1039f471e5..41caee35fa 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -335,9 +335,6 @@ private:
status_t electronBeamOffAnimationImplLocked();
status_t electronBeamOnAnimationImplLocked();
- void cleanupDisplayEventConnection(
- const wp<DisplayEventConnection>& connection);
-
void debugFlashRegions();
void debugShowFPS() const;
void drawWormhole() const;
@@ -352,6 +349,7 @@ private:
Condition mTransactionCV;
SortedVector< sp<LayerBase> > mLayerPurgatory;
bool mTransationPending;
+ Vector< sp<LayerBase> > mLayersPendingRemoval;
// protected by mStateLock (but we could use another lock)
GraphicPlane mGraphicPlanes[1];