Merge "separate transactions from updates"
This commit is contained in:
commit
064b68d1bc
@ -95,6 +95,8 @@ public:
|
|||||||
* should be destroyed and getEvents() shouldn't be called again.
|
* should be destroyed and getEvents() shouldn't be called again.
|
||||||
*/
|
*/
|
||||||
ssize_t getEvents(Event* events, size_t count);
|
ssize_t getEvents(Event* events, size_t count);
|
||||||
|
static ssize_t getEvents(const sp<BitTube>& dataChannel,
|
||||||
|
Event* events, size_t count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* setVsyncRate() sets the Event::VSync delivery rate. A value of
|
* setVsyncRate() sets the Event::VSync delivery rate. A value of
|
||||||
|
@ -80,7 +80,13 @@ status_t DisplayEventReceiver::requestNextVsync() {
|
|||||||
|
|
||||||
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
|
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
|
||||||
size_t count) {
|
size_t count) {
|
||||||
ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
|
return DisplayEventReceiver::getEvents(mDataChannel, events, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
|
||||||
|
Event* events, size_t count)
|
||||||
|
{
|
||||||
|
ssize_t size = dataChannel->read(events, sizeof(events[0])*count);
|
||||||
ALOGE_IF(size<0,
|
ALOGE_IF(size<0,
|
||||||
"DisplayEventReceiver::getEvents error (%s)",
|
"DisplayEventReceiver::getEvents error (%s)",
|
||||||
strerror(-size));
|
strerror(-size));
|
||||||
|
@ -32,7 +32,6 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3)
|
|||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
|
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
|
||||||
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
|
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
|
||||||
LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
|
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
|
||||||
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
|
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
|
||||||
|
@ -55,6 +55,7 @@ Layer::Layer(SurfaceFlinger* flinger,
|
|||||||
mCurrentTransform(0),
|
mCurrentTransform(0),
|
||||||
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
||||||
mCurrentOpacity(true),
|
mCurrentOpacity(true),
|
||||||
|
mRefreshPending(0),
|
||||||
mFrameLatencyNeeded(false),
|
mFrameLatencyNeeded(false),
|
||||||
mFrameLatencyOffset(0),
|
mFrameLatencyOffset(0),
|
||||||
mFormat(PIXEL_FORMAT_NONE),
|
mFormat(PIXEL_FORMAT_NONE),
|
||||||
@ -97,12 +98,7 @@ void Layer::onFirstRef()
|
|||||||
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
|
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
|
||||||
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
|
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
|
||||||
mSurfaceTexture->setSynchronousMode(true);
|
mSurfaceTexture->setSynchronousMode(true);
|
||||||
#ifdef USE_TRIPLE_BUFFERING
|
|
||||||
#warning "using triple buffering"
|
|
||||||
mSurfaceTexture->setBufferCountServer(3);
|
|
||||||
#else
|
|
||||||
mSurfaceTexture->setBufferCountServer(2);
|
mSurfaceTexture->setBufferCountServer(2);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Layer::~Layer()
|
Layer::~Layer()
|
||||||
@ -113,7 +109,7 @@ Layer::~Layer()
|
|||||||
|
|
||||||
void Layer::onFrameQueued() {
|
void Layer::onFrameQueued() {
|
||||||
android_atomic_inc(&mQueuedFrames);
|
android_atomic_inc(&mQueuedFrames);
|
||||||
mFlinger->signalEvent();
|
mFlinger->signalLayerUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
|
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
|
||||||
@ -407,16 +403,37 @@ bool Layer::isCropped() const {
|
|||||||
// pageflip handling...
|
// pageflip handling...
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool Layer::onPreComposition()
|
||||||
|
{
|
||||||
|
// if there was more than one pending update, request a refresh
|
||||||
|
if (mRefreshPending >= 2) {
|
||||||
|
mRefreshPending = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
mRefreshPending = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||||
{
|
{
|
||||||
if (mQueuedFrames > 0) {
|
if (mQueuedFrames > 0) {
|
||||||
|
|
||||||
|
// if we've already called updateTexImage() without going through
|
||||||
|
// a composition step, we have to skip this layer at this point
|
||||||
|
// because we cannot call updateTeximage() without a corresponding
|
||||||
|
// compositionComplete() call.
|
||||||
|
// we'll trigger an update in onPreComposition().
|
||||||
|
if (mRefreshPending++) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Capture the old state of the layer for comparisons later
|
// Capture the old state of the layer for comparisons later
|
||||||
const bool oldOpacity = isOpaque();
|
const bool oldOpacity = isOpaque();
|
||||||
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
|
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
|
||||||
|
|
||||||
// signal another event if we have more frames pending
|
// signal another event if we have more frames pending
|
||||||
if (android_atomic_dec(&mQueuedFrames) > 1) {
|
if (android_atomic_dec(&mQueuedFrames) > 1) {
|
||||||
mFlinger->signalEvent();
|
mFlinger->signalLayerUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
|
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
|
||||||
@ -519,6 +536,10 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
|||||||
void Layer::unlockPageFlip(
|
void Layer::unlockPageFlip(
|
||||||
const Transform& planeTransform, Region& outDirtyRegion)
|
const Transform& planeTransform, Region& outDirtyRegion)
|
||||||
{
|
{
|
||||||
|
if (mRefreshPending >= 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Region dirtyRegion(mPostedDirtyRegion);
|
Region dirtyRegion(mPostedDirtyRegion);
|
||||||
if (!dirtyRegion.isEmpty()) {
|
if (!dirtyRegion.isEmpty()) {
|
||||||
mPostedDirtyRegion.clear();
|
mPostedDirtyRegion.clear();
|
||||||
@ -552,9 +573,9 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
|||||||
snprintf(buffer, SIZE,
|
snprintf(buffer, SIZE,
|
||||||
" "
|
" "
|
||||||
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
|
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
|
||||||
" transform-hint=0x%02x, queued-frames=%d\n",
|
" transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
|
||||||
mFormat, w0, h0, s0,f0,
|
mFormat, w0, h0, s0,f0,
|
||||||
getTransformHint(), mQueuedFrames);
|
getTransformHint(), mQueuedFrames, mRefreshPending);
|
||||||
|
|
||||||
result.append(buffer);
|
result.append(buffer);
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ public:
|
|||||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||||
|
|
||||||
virtual void onLayerDisplayed();
|
virtual void onLayerDisplayed();
|
||||||
|
virtual bool onPreComposition();
|
||||||
|
|
||||||
// only for debugging
|
// only for debugging
|
||||||
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
||||||
@ -115,14 +116,17 @@ private:
|
|||||||
uint32_t mCurrentTransform;
|
uint32_t mCurrentTransform;
|
||||||
uint32_t mCurrentScalingMode;
|
uint32_t mCurrentScalingMode;
|
||||||
bool mCurrentOpacity;
|
bool mCurrentOpacity;
|
||||||
|
size_t mRefreshPending;
|
||||||
bool mFrameLatencyNeeded;
|
bool mFrameLatencyNeeded;
|
||||||
int mFrameLatencyOffset;
|
int mFrameLatencyOffset;
|
||||||
|
|
||||||
struct Statistics {
|
struct Statistics {
|
||||||
Statistics() : timestamp(0), set(0), vsync(0) { }
|
Statistics() : timestamp(0), set(0), vsync(0) { }
|
||||||
nsecs_t timestamp; // buffer timestamp
|
nsecs_t timestamp; // buffer timestamp
|
||||||
nsecs_t set; // buffer displayed timestamp
|
nsecs_t set; // buffer displayed timestamp
|
||||||
nsecs_t vsync; // vsync immediately before set
|
nsecs_t vsync; // vsync immediately before set
|
||||||
};
|
};
|
||||||
|
|
||||||
// protected by mLock
|
// protected by mLock
|
||||||
Statistics mFrameStats[128];
|
Statistics mFrameStats[128];
|
||||||
|
|
||||||
|
@ -47,8 +47,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
|||||||
mOrientation(0),
|
mOrientation(0),
|
||||||
mPlaneOrientation(0),
|
mPlaneOrientation(0),
|
||||||
mTransactionFlags(0),
|
mTransactionFlags(0),
|
||||||
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
|
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
|
||||||
mInvalidate(0)
|
|
||||||
{
|
{
|
||||||
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
|
||||||
mFlags = hw.getFlags();
|
mFlags = hw.getFlags();
|
||||||
@ -262,23 +261,11 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
|
|||||||
mTransformedBounds = tr.makeBounds(w, h);
|
mTransformedBounds = tr.makeBounds(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
|
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerBase::unlockPageFlip(
|
void LayerBase::unlockPageFlip(
|
||||||
const Transform& planeTransform, Region& outDirtyRegion)
|
const Transform& planeTransform, Region& outDirtyRegion) {
|
||||||
{
|
|
||||||
if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
|
|
||||||
outDirtyRegion.orSelf(visibleRegionScreen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerBase::invalidate()
|
|
||||||
{
|
|
||||||
if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
|
|
||||||
mFlinger->signalEvent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerBase::drawRegion(const Region& reg) const
|
void LayerBase::drawRegion(const Region& reg) const
|
||||||
|
@ -103,8 +103,6 @@ public:
|
|||||||
Rect visibleBounds() const;
|
Rect visibleBounds() const;
|
||||||
void drawRegion(const Region& reg) const;
|
void drawRegion(const Region& reg) const;
|
||||||
|
|
||||||
void invalidate();
|
|
||||||
|
|
||||||
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
|
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
|
||||||
virtual sp<Layer> getLayer() const { return 0; }
|
virtual sp<Layer> getLayer() const { return 0; }
|
||||||
|
|
||||||
@ -204,9 +202,16 @@ public:
|
|||||||
|
|
||||||
/** called with the state lock when the surface is removed from the
|
/** called with the state lock when the surface is removed from the
|
||||||
* current list */
|
* current list */
|
||||||
virtual void onRemoved() { };
|
virtual void onRemoved() { }
|
||||||
|
|
||||||
virtual void onLayerDisplayed() { };
|
/** called after page-flip
|
||||||
|
*/
|
||||||
|
virtual void onLayerDisplayed() { }
|
||||||
|
|
||||||
|
/** called before composition.
|
||||||
|
* returns true if the layer has pending updates.
|
||||||
|
*/
|
||||||
|
virtual bool onPreComposition() { return false; }
|
||||||
|
|
||||||
/** always call base class first */
|
/** always call base class first */
|
||||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||||
@ -275,10 +280,6 @@ protected:
|
|||||||
mutable bool mDebug;
|
mutable bool mDebug;
|
||||||
|
|
||||||
|
|
||||||
// atomic
|
|
||||||
volatile int32_t mInvalidate;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// called from class SurfaceFlinger
|
// called from class SurfaceFlinger
|
||||||
virtual ~LayerBase();
|
virtual ~LayerBase();
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "MessageQueue.h"
|
#include "MessageQueue.h"
|
||||||
#include "EventThread.h"
|
#include "EventThread.h"
|
||||||
|
#include "SurfaceFlinger.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@ -48,14 +49,47 @@ void MessageBase::handleMessage(const Message&) {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void MessageQueue::Handler::signalRefresh() {
|
||||||
|
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
|
||||||
|
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageQueue::Handler::signalInvalidate() {
|
||||||
|
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
|
||||||
|
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageQueue::Handler::handleMessage(const Message& message) {
|
||||||
|
switch (message.what) {
|
||||||
|
case INVALIDATE:
|
||||||
|
android_atomic_and(~eventMaskInvalidate, &mEventMask);
|
||||||
|
mQueue.mFlinger->onMessageReceived(message.what);
|
||||||
|
break;
|
||||||
|
case REFRESH:
|
||||||
|
android_atomic_and(~eventMaskRefresh, &mEventMask);
|
||||||
|
mQueue.mFlinger->onMessageReceived(message.what);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
MessageQueue::MessageQueue()
|
MessageQueue::MessageQueue()
|
||||||
: mLooper(new Looper(true)), mWorkPending(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue::~MessageQueue() {
|
MessageQueue::~MessageQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
|
||||||
|
{
|
||||||
|
mFlinger = flinger;
|
||||||
|
mLooper = new Looper(true);
|
||||||
|
mHandler = new Handler(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
|
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
|
||||||
{
|
{
|
||||||
mEventThread = eventThread;
|
mEventThread = eventThread;
|
||||||
@ -68,25 +102,16 @@ void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
|
|||||||
void MessageQueue::waitMessage() {
|
void MessageQueue::waitMessage() {
|
||||||
do {
|
do {
|
||||||
IPCThreadState::self()->flushCommands();
|
IPCThreadState::self()->flushCommands();
|
||||||
|
|
||||||
int32_t ret = mLooper->pollOnce(-1);
|
int32_t ret = mLooper->pollOnce(-1);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case ALOOPER_POLL_WAKE:
|
case ALOOPER_POLL_WAKE:
|
||||||
case ALOOPER_POLL_CALLBACK:
|
case ALOOPER_POLL_CALLBACK:
|
||||||
// callback and/or wake
|
|
||||||
if (android_atomic_and(0, &mWorkPending)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
|
case ALOOPER_POLL_ERROR:
|
||||||
|
ALOGE("ALOOPER_POLL_ERROR");
|
||||||
case ALOOPER_POLL_TIMEOUT:
|
case ALOOPER_POLL_TIMEOUT:
|
||||||
// timeout (should not happen)
|
// timeout (should not happen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case ALOOPER_POLL_ERROR:
|
|
||||||
ALOGE("ALOOPER_POLL_ERROR");
|
|
||||||
continue;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// should not happen
|
// should not happen
|
||||||
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
|
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
|
||||||
@ -107,15 +132,12 @@ status_t MessageQueue::postMessage(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueue::scheduleWorkASAP() {
|
void MessageQueue::invalidate() {
|
||||||
if (android_atomic_or(1, &mWorkPending) == 0) {
|
mHandler->signalInvalidate();
|
||||||
mLooper->wake();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t MessageQueue::invalidate() {
|
void MessageQueue::refresh() {
|
||||||
mEvents->requestNextVsync();
|
mEvents->requestNextVsync();
|
||||||
return NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
|
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
|
||||||
@ -126,10 +148,10 @@ int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
|
|||||||
int MessageQueue::eventReceiver(int fd, int events) {
|
int MessageQueue::eventReceiver(int fd, int events) {
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
DisplayEventReceiver::Event buffer[8];
|
DisplayEventReceiver::Event buffer[8];
|
||||||
while ((n = getEvents(buffer, 8)) > 0) {
|
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
|
||||||
for (int i=0 ; i<n ; i++) {
|
for (int i=0 ; i<n ; i++) {
|
||||||
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
|
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
|
||||||
scheduleWorkASAP();
|
mHandler->signalRefresh();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,24 +159,6 @@ int MessageQueue::eventReceiver(int fd, int events) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t MessageQueue::getEvents(
|
|
||||||
DisplayEventReceiver::Event* events, size_t count)
|
|
||||||
{
|
|
||||||
ssize_t size = mEventTube->read(events, sizeof(events[0])*count);
|
|
||||||
ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size));
|
|
||||||
if (size >= 0) {
|
|
||||||
// Note: if (size % sizeof(events[0])) != 0, we've got a
|
|
||||||
// partial read. This can happen if the queue filed up (ie: if we
|
|
||||||
// didn't pull from it fast enough).
|
|
||||||
// We discard the partial event and rely on the sender to
|
|
||||||
// re-send the event if appropriate (some events, like VSYNC
|
|
||||||
// can be lost forever).
|
|
||||||
// returns number of events read
|
|
||||||
size /= sizeof(events[0]);
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -33,6 +33,7 @@ namespace android {
|
|||||||
|
|
||||||
class IDisplayEventConnection;
|
class IDisplayEventConnection;
|
||||||
class EventThread;
|
class EventThread;
|
||||||
|
class SurfaceFlinger;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -59,25 +60,48 @@ private:
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class MessageQueue {
|
class MessageQueue {
|
||||||
|
class Handler : public MessageHandler {
|
||||||
|
enum {
|
||||||
|
eventMaskInvalidate = 0x1,
|
||||||
|
eventMaskRefresh = 0x2
|
||||||
|
};
|
||||||
|
MessageQueue& mQueue;
|
||||||
|
int32_t mEventMask;
|
||||||
|
public:
|
||||||
|
Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
|
||||||
|
virtual void handleMessage(const Message& message);
|
||||||
|
void signalRefresh();
|
||||||
|
void signalInvalidate();
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class Handler;
|
||||||
|
|
||||||
|
sp<SurfaceFlinger> mFlinger;
|
||||||
sp<Looper> mLooper;
|
sp<Looper> mLooper;
|
||||||
sp<EventThread> mEventThread;
|
sp<EventThread> mEventThread;
|
||||||
sp<IDisplayEventConnection> mEvents;
|
sp<IDisplayEventConnection> mEvents;
|
||||||
sp<BitTube> mEventTube;
|
sp<BitTube> mEventTube;
|
||||||
int32_t mWorkPending;
|
sp<Handler> mHandler;
|
||||||
|
|
||||||
|
|
||||||
static int cb_eventReceiver(int fd, int events, void* data);
|
static int cb_eventReceiver(int fd, int events, void* data);
|
||||||
int eventReceiver(int fd, int events);
|
int eventReceiver(int fd, int events);
|
||||||
ssize_t getEvents(DisplayEventReceiver::Event* events, size_t count);
|
|
||||||
void scheduleWorkASAP();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum {
|
||||||
|
INVALIDATE = 0,
|
||||||
|
REFRESH = 1,
|
||||||
|
};
|
||||||
|
|
||||||
MessageQueue();
|
MessageQueue();
|
||||||
~MessageQueue();
|
~MessageQueue();
|
||||||
|
void init(const sp<SurfaceFlinger>& flinger);
|
||||||
void setEventThread(const sp<EventThread>& events);
|
void setEventThread(const sp<EventThread>& events);
|
||||||
|
|
||||||
void waitMessage();
|
void waitMessage();
|
||||||
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
|
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
|
||||||
status_t invalidate();
|
void invalidate();
|
||||||
|
void refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -125,11 +125,34 @@ void SurfaceFlinger::init()
|
|||||||
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
|
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::onFirstRef()
|
||||||
|
{
|
||||||
|
mEventQueue.init(this);
|
||||||
|
|
||||||
|
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
|
||||||
|
|
||||||
|
// Wait for the main thread to be done with its initialization
|
||||||
|
mReadyToRunBarrier.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SurfaceFlinger::~SurfaceFlinger()
|
SurfaceFlinger::~SurfaceFlinger()
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &mWormholeTexName);
|
glDeleteTextures(1, &mWormholeTexName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
|
||||||
|
{
|
||||||
|
// the window manager died on us. prepare its eulogy.
|
||||||
|
|
||||||
|
// reset screen orientation
|
||||||
|
Vector<ComposerState> state;
|
||||||
|
setTransactionState(state, eOrientationDefault, 0);
|
||||||
|
|
||||||
|
// restart the boot-animation
|
||||||
|
property_set("ctl.start", "bootanim");
|
||||||
|
}
|
||||||
|
|
||||||
sp<IMemoryHeap> SurfaceFlinger::getCblk() const
|
sp<IMemoryHeap> SurfaceFlinger::getCblk() const
|
||||||
{
|
{
|
||||||
return mServerHeap;
|
return mServerHeap;
|
||||||
@ -183,26 +206,6 @@ void SurfaceFlinger::bootFinished()
|
|||||||
property_set("ctl.stop", "bootanim");
|
property_set("ctl.stop", "bootanim");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
|
|
||||||
{
|
|
||||||
// the window manager died on us. prepare its eulogy.
|
|
||||||
|
|
||||||
// reset screen orientation
|
|
||||||
Vector<ComposerState> state;
|
|
||||||
setTransactionState(state, eOrientationDefault, 0);
|
|
||||||
|
|
||||||
// restart the boot-animation
|
|
||||||
property_set("ctl.start", "bootanim");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SurfaceFlinger::onFirstRef()
|
|
||||||
{
|
|
||||||
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
|
|
||||||
|
|
||||||
// Wait for the main thread to be done with its initialization
|
|
||||||
mReadyToRunBarrier.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t pack565(int r, int g, int b) {
|
static inline uint16_t pack565(int r, int g, int b) {
|
||||||
return (r<<11)|(g<<5)|b;
|
return (r<<11)|(g<<5)|b;
|
||||||
}
|
}
|
||||||
@ -310,34 +313,6 @@ status_t SurfaceFlinger::readyToRun()
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
#if 0
|
|
||||||
#pragma mark -
|
|
||||||
#pragma mark Events Handler
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SurfaceFlinger::waitForEvent() {
|
|
||||||
mEventQueue.waitMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SurfaceFlinger::signalEvent() {
|
|
||||||
mEventQueue.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
|
|
||||||
nsecs_t reltime, uint32_t flags) {
|
|
||||||
return mEventQueue.postMessage(msg, reltime);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
|
|
||||||
nsecs_t reltime, uint32_t flags) {
|
|
||||||
status_t res = mEventQueue.postMessage(msg, reltime);
|
|
||||||
if (res == NO_ERROR) {
|
|
||||||
msg->wait();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool SurfaceFlinger::authenticateSurfaceTexture(
|
bool SurfaceFlinger::authenticateSurfaceTexture(
|
||||||
@ -388,54 +363,93 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
#if 0
|
|
||||||
#pragma mark -
|
void SurfaceFlinger::waitForEvent() {
|
||||||
#pragma mark Main loop
|
mEventQueue.waitMessage();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::signalTransaction() {
|
||||||
|
mEventQueue.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::signalLayerUpdate() {
|
||||||
|
mEventQueue.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::signalRefresh() {
|
||||||
|
mEventQueue.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
|
||||||
|
nsecs_t reltime, uint32_t flags) {
|
||||||
|
return mEventQueue.postMessage(msg, reltime);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
|
||||||
|
nsecs_t reltime, uint32_t flags) {
|
||||||
|
status_t res = mEventQueue.postMessage(msg, reltime);
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
msg->wait();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
bool SurfaceFlinger::threadLoop()
|
bool SurfaceFlinger::threadLoop()
|
||||||
{
|
{
|
||||||
waitForEvent();
|
waitForEvent();
|
||||||
|
|
||||||
// check for transactions
|
|
||||||
if (CC_UNLIKELY(mConsoleSignals)) {
|
|
||||||
handleConsoleEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're in a global transaction, don't do anything.
|
|
||||||
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
|
||||||
uint32_t transactionFlags = peekTransactionFlags(mask);
|
|
||||||
if (CC_UNLIKELY(transactionFlags)) {
|
|
||||||
handleTransaction(transactionFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// post surfaces (if needed)
|
|
||||||
handlePageFlip();
|
|
||||||
|
|
||||||
if (mDirtyRegion.isEmpty()) {
|
|
||||||
// nothing new to do.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CC_UNLIKELY(mHwWorkListDirty)) {
|
|
||||||
// build the h/w work list
|
|
||||||
handleWorkList();
|
|
||||||
}
|
|
||||||
|
|
||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
|
||||||
if (CC_LIKELY(hw.canDraw())) {
|
|
||||||
// repaint the framebuffer (if needed)
|
|
||||||
handleRepaint();
|
|
||||||
// inform the h/w that we're done compositing
|
|
||||||
hw.compositionComplete();
|
|
||||||
postFramebuffer();
|
|
||||||
} else {
|
|
||||||
// pretend we did the post
|
|
||||||
hw.compositionComplete();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::onMessageReceived(int32_t what)
|
||||||
|
{
|
||||||
|
switch (what) {
|
||||||
|
case MessageQueue::INVALIDATE: {
|
||||||
|
// check for transactions
|
||||||
|
if (CC_UNLIKELY(mConsoleSignals)) {
|
||||||
|
handleConsoleEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're in a global transaction, don't do anything.
|
||||||
|
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
||||||
|
uint32_t transactionFlags = peekTransactionFlags(mask);
|
||||||
|
if (CC_UNLIKELY(transactionFlags)) {
|
||||||
|
handleTransaction(transactionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// post surfaces (if needed)
|
||||||
|
handlePageFlip();
|
||||||
|
|
||||||
|
if (!mDirtyRegion.isEmpty()) {
|
||||||
|
signalRefresh();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MessageQueue::REFRESH: {
|
||||||
|
if (!mDirtyRegion.isEmpty()) {
|
||||||
|
// NOTE: it is mandatory to call hw.compositionComplete()
|
||||||
|
// after handleRefresh()
|
||||||
|
handleRefresh();
|
||||||
|
|
||||||
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
|
if (CC_UNLIKELY(mHwWorkListDirty)) {
|
||||||
|
// build the h/w work list
|
||||||
|
handleWorkList();
|
||||||
|
}
|
||||||
|
if (CC_LIKELY(hw.canDraw())) {
|
||||||
|
// repaint the framebuffer (if needed)
|
||||||
|
handleRepaint();
|
||||||
|
// inform the h/w that we're done compositing
|
||||||
|
hw.compositionComplete();
|
||||||
|
postFramebuffer();
|
||||||
|
} else {
|
||||||
|
// pretend we did the post
|
||||||
|
hw.compositionComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::postFramebuffer()
|
void SurfaceFlinger::postFramebuffer()
|
||||||
{
|
{
|
||||||
// this should never happen. we do the flip anyways so we don't
|
// this should never happen. we do the flip anyways so we don't
|
||||||
@ -717,13 +731,13 @@ void SurfaceFlinger::commitTransaction()
|
|||||||
|
|
||||||
void SurfaceFlinger::handlePageFlip()
|
void SurfaceFlinger::handlePageFlip()
|
||||||
{
|
{
|
||||||
bool visibleRegions = mVisibleRegionsDirty;
|
const DisplayHardware& hw = graphicPlane(0).displayHardware();
|
||||||
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
const Region screenRegion(hw.bounds());
|
||||||
visibleRegions |= lockPageFlip(currentLayers);
|
|
||||||
|
|
||||||
const DisplayHardware& hw = graphicPlane(0).displayHardware();
|
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||||
const Region screenRegion(hw.bounds());
|
const bool visibleRegions = lockPageFlip(currentLayers);
|
||||||
if (visibleRegions) {
|
|
||||||
|
if (visibleRegions || mVisibleRegionsDirty) {
|
||||||
Region opaqueRegion;
|
Region opaqueRegion;
|
||||||
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
|
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
|
||||||
|
|
||||||
@ -770,7 +784,7 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
|||||||
{
|
{
|
||||||
const GraphicPlane& plane(graphicPlane(0));
|
const GraphicPlane& plane(graphicPlane(0));
|
||||||
const Transform& planeTransform(plane.transform());
|
const Transform& planeTransform(plane.transform());
|
||||||
size_t count = currentLayers.size();
|
const size_t count = currentLayers.size();
|
||||||
sp<LayerBase> const* layers = currentLayers.array();
|
sp<LayerBase> const* layers = currentLayers.array();
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
const sp<LayerBase>& layer(layers[i]);
|
const sp<LayerBase>& layer(layers[i]);
|
||||||
@ -778,6 +792,23 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::handleRefresh()
|
||||||
|
{
|
||||||
|
bool needInvalidate = false;
|
||||||
|
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||||
|
const size_t count = currentLayers.size();
|
||||||
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
|
const sp<LayerBase>& layer(currentLayers[i]);
|
||||||
|
if (layer->onPreComposition()) {
|
||||||
|
needInvalidate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needInvalidate) {
|
||||||
|
signalLayerUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SurfaceFlinger::handleWorkList()
|
void SurfaceFlinger::handleWorkList()
|
||||||
{
|
{
|
||||||
mHwWorkListDirty = false;
|
mHwWorkListDirty = false;
|
||||||
@ -1175,7 +1206,7 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
|
|||||||
{
|
{
|
||||||
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
|
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
|
||||||
if ((old & flags)==0) { // wake the server up
|
if ((old & flags)==0) { // wake the server up
|
||||||
signalEvent();
|
signalTransaction();
|
||||||
}
|
}
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
@ -1426,14 +1457,14 @@ void SurfaceFlinger::screenReleased(int dpy)
|
|||||||
{
|
{
|
||||||
// this may be called by a signal handler, we can't do too much in here
|
// this may be called by a signal handler, we can't do too much in here
|
||||||
android_atomic_or(eConsoleReleased, &mConsoleSignals);
|
android_atomic_or(eConsoleReleased, &mConsoleSignals);
|
||||||
signalEvent();
|
signalTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::screenAcquired(int dpy)
|
void SurfaceFlinger::screenAcquired(int dpy)
|
||||||
{
|
{
|
||||||
// this may be called by a signal handler, we can't do too much in here
|
// this may be called by a signal handler, we can't do too much in here
|
||||||
android_atomic_or(eConsoleAcquired, &mConsoleSignals);
|
android_atomic_or(eConsoleAcquired, &mConsoleSignals);
|
||||||
signalEvent();
|
signalTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||||
@ -1769,7 +1800,7 @@ void SurfaceFlinger::repaintEverything() {
|
|||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
const Rect bounds(hw.getBounds());
|
const Rect bounds(hw.getBounds());
|
||||||
setInvalidateRegion(Region(bounds));
|
setInvalidateRegion(Region(bounds));
|
||||||
signalEvent();
|
signalTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
|
void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
|
||||||
@ -2245,7 +2276,7 @@ status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
|
|||||||
|
|
||||||
// make sure to redraw the whole screen when the animation is done
|
// make sure to redraw the whole screen when the animation is done
|
||||||
mDirtyRegion.set(hw.bounds());
|
mDirtyRegion.set(hw.bounds());
|
||||||
signalEvent();
|
signalTransaction();
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -190,6 +190,8 @@ public:
|
|||||||
status_t renderScreenToTextureLocked(DisplayID dpy,
|
status_t renderScreenToTextureLocked(DisplayID dpy,
|
||||||
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
|
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
|
||||||
|
|
||||||
|
void onMessageReceived(int32_t what);
|
||||||
|
|
||||||
status_t postMessageAsync(const sp<MessageBase>& msg,
|
status_t postMessageAsync(const sp<MessageBase>& msg,
|
||||||
nsecs_t reltime=0, uint32_t flags = 0);
|
nsecs_t reltime=0, uint32_t flags = 0);
|
||||||
|
|
||||||
@ -283,7 +285,10 @@ private:
|
|||||||
public: // hack to work around gcc 4.0.3 bug
|
public: // hack to work around gcc 4.0.3 bug
|
||||||
const GraphicPlane& graphicPlane(int dpy) const;
|
const GraphicPlane& graphicPlane(int dpy) const;
|
||||||
GraphicPlane& graphicPlane(int dpy);
|
GraphicPlane& graphicPlane(int dpy);
|
||||||
void signalEvent();
|
|
||||||
|
void signalTransaction();
|
||||||
|
void signalLayerUpdate();
|
||||||
|
void signalRefresh();
|
||||||
void repaintEverything();
|
void repaintEverything();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -300,6 +305,7 @@ private:
|
|||||||
void handlePageFlip();
|
void handlePageFlip();
|
||||||
bool lockPageFlip(const LayerVector& currentLayers);
|
bool lockPageFlip(const LayerVector& currentLayers);
|
||||||
void unlockPageFlip(const LayerVector& currentLayers);
|
void unlockPageFlip(const LayerVector& currentLayers);
|
||||||
|
void handleRefresh();
|
||||||
void handleWorkList();
|
void handleWorkList();
|
||||||
void handleRepaint();
|
void handleRepaint();
|
||||||
void postFramebuffer();
|
void postFramebuffer();
|
||||||
|
Loading…
Reference in New Issue
Block a user