Merge "Add support for sending VSYNC events to the framework"
This commit is contained in:
commit
cb38a34257
105
include/gui/DisplayEventReceiver.h
Normal file
105
include/gui/DisplayEventReceiver.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_GUI_DISPLAY_EVENT_H
|
||||
#define ANDROID_GUI_DISPLAY_EVENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <binder/IInterface.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BitTube;
|
||||
class IDisplayEventConnection;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class DisplayEventReceiver {
|
||||
public:
|
||||
enum {
|
||||
DISPLAY_EVENT_VSYNC = 'vsyn'
|
||||
};
|
||||
|
||||
struct Event {
|
||||
|
||||
struct Header {
|
||||
uint32_t type;
|
||||
nsecs_t timestamp;
|
||||
};
|
||||
|
||||
struct VSync {
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
Header header;
|
||||
union {
|
||||
VSync vsync;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
/*
|
||||
* DisplayEventReceiver creates and registers an event connection with
|
||||
* SurfaceFlinger. Events start being delivered immediately.
|
||||
*/
|
||||
DisplayEventReceiver();
|
||||
|
||||
/*
|
||||
* ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
|
||||
* stop being delivered immediately. Note that the queue could have
|
||||
* some events pending. These will be delivered.
|
||||
*/
|
||||
~DisplayEventReceiver();
|
||||
|
||||
/*
|
||||
* initCheck returns the state of DisplayEventReceiver after construction.
|
||||
*/
|
||||
status_t initCheck() const;
|
||||
|
||||
/*
|
||||
* getFd returns the file descriptor to use to receive events.
|
||||
* OWNERSHIP IS RETAINED by DisplayEventReceiver. DO NOT CLOSE this
|
||||
* file-descriptor.
|
||||
*/
|
||||
int getFd() const;
|
||||
|
||||
/*
|
||||
* getEvents reads event from the queue and returns how many events were
|
||||
* read. Returns 0 if there are no more events or a negative error code.
|
||||
* If NOT_ENOUGH_DATA is returned, the object has become invalid forever, it
|
||||
* should be destroyed and getEvents() shouldn't be called again.
|
||||
*/
|
||||
ssize_t getEvents(Event* events, size_t count);
|
||||
|
||||
private:
|
||||
sp<IDisplayEventConnection> mEventConnection;
|
||||
sp<BitTube> mDataChannel;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_GUI_DISPLAY_EVENT_H
|
55
include/gui/IDisplayEventConnection.h
Normal file
55
include/gui/IDisplayEventConnection.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
|
||||
#define ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include <binder/IInterface.h>
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BitTube;
|
||||
|
||||
class IDisplayEventConnection : public IInterface
|
||||
{
|
||||
public:
|
||||
DECLARE_META_INTERFACE(DisplayEventConnection);
|
||||
|
||||
virtual sp<BitTube> getDataChannel() const = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BnDisplayEventConnection : public BnInterface<IDisplayEventConnection>
|
||||
{
|
||||
public:
|
||||
virtual status_t onTransact( uint32_t code,
|
||||
const Parcel& data,
|
||||
Parcel* reply,
|
||||
uint32_t flags = 0);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
|
@ -33,8 +33,9 @@
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class IMemoryHeap;
|
||||
class ComposerState;
|
||||
class IDisplayEventConnection;
|
||||
class IMemoryHeap;
|
||||
|
||||
class ISurfaceComposer : public IInterface
|
||||
{
|
||||
@ -124,13 +125,19 @@ public:
|
||||
uint32_t reqWidth, uint32_t reqHeight,
|
||||
uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
|
||||
|
||||
/* triggers screen off animation */
|
||||
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
|
||||
|
||||
/* triggers screen on animation */
|
||||
virtual status_t turnElectronBeamOn(int32_t mode) = 0;
|
||||
|
||||
/* verify that an ISurfaceTexture was created by SurfaceFlinger.
|
||||
*/
|
||||
virtual bool authenticateSurfaceTexture(
|
||||
const sp<ISurfaceTexture>& surface) const = 0;
|
||||
|
||||
/* return an IDisplayEventConnection */
|
||||
virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -151,6 +158,7 @@ public:
|
||||
TURN_ELECTRON_BEAM_OFF,
|
||||
TURN_ELECTRON_BEAM_ON,
|
||||
AUTHENTICATE_SURFACE,
|
||||
CREATE_DISPLAY_EVENT_CONNECTION,
|
||||
};
|
||||
|
||||
virtual status_t onTransact( uint32_t code,
|
||||
|
@ -3,6 +3,8 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
BitTube.cpp \
|
||||
DisplayEventReceiver.cpp \
|
||||
IDisplayEventConnection.cpp \
|
||||
ISensorEventConnection.cpp \
|
||||
ISensorServer.cpp \
|
||||
ISurfaceTexture.cpp \
|
||||
|
83
libs/gui/DisplayEventReceiver.cpp
Normal file
83
libs/gui/DisplayEventReceiver.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include <gui/BitTube.h>
|
||||
#include <gui/DisplayEventReceiver.h>
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
|
||||
#include <private/gui/ComposerService.h>
|
||||
|
||||
#include <surfaceflinger/ISurfaceComposer.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
DisplayEventReceiver::DisplayEventReceiver() {
|
||||
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
|
||||
if (sf != NULL) {
|
||||
mEventConnection = sf->createDisplayEventConnection();
|
||||
if (mEventConnection != NULL) {
|
||||
mDataChannel = mEventConnection->getDataChannel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisplayEventReceiver::~DisplayEventReceiver() {
|
||||
}
|
||||
|
||||
status_t DisplayEventReceiver::initCheck() const {
|
||||
if (mDataChannel != NULL)
|
||||
return NO_ERROR;
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
int DisplayEventReceiver::getFd() const {
|
||||
if (mDataChannel == NULL)
|
||||
return NO_INIT;
|
||||
|
||||
return mDataChannel->getFd();
|
||||
}
|
||||
|
||||
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
|
||||
size_t count) {
|
||||
ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
|
||||
LOGE_IF(size<0,
|
||||
"DisplayEventReceiver::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
|
73
libs/gui/IDisplayEventConnection.cpp
Normal file
73
libs/gui/IDisplayEventConnection.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <binder/Parcel.h>
|
||||
#include <binder/IInterface.h>
|
||||
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
#include <gui/BitTube.h>
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
enum {
|
||||
GET_DATA_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
|
||||
};
|
||||
|
||||
class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection>
|
||||
{
|
||||
public:
|
||||
BpDisplayEventConnection(const sp<IBinder>& impl)
|
||||
: BpInterface<IDisplayEventConnection>(impl)
|
||||
{
|
||||
}
|
||||
|
||||
virtual sp<BitTube> getDataChannel() const
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
|
||||
remote()->transact(GET_DATA_CHANNEL, data, &reply);
|
||||
return new BitTube(reply);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection");
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
status_t BnDisplayEventConnection::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
switch(code) {
|
||||
case GET_DATA_CHANNEL: {
|
||||
CHECK_INTERFACE(IDisplayEventConnection, data, reply);
|
||||
sp<BitTube> channel(getDataChannel());
|
||||
channel->writeToParcel(reply);
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
}
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
@ -29,6 +29,9 @@
|
||||
|
||||
#include <surfaceflinger/ISurfaceComposer.h>
|
||||
|
||||
#include <gui/BitTube.h>
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
|
||||
#include <gui/ISurfaceTexture.h>
|
||||
@ -44,6 +47,8 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
class IDisplayEventConnection;
|
||||
|
||||
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
|
||||
{
|
||||
public:
|
||||
@ -174,6 +179,27 @@ public:
|
||||
}
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
virtual sp<IDisplayEventConnection> createDisplayEventConnection()
|
||||
{
|
||||
Parcel data, reply;
|
||||
sp<IDisplayEventConnection> result;
|
||||
int err = data.writeInterfaceToken(
|
||||
ISurfaceComposer::getInterfaceDescriptor());
|
||||
if (err != NO_ERROR) {
|
||||
return result;
|
||||
}
|
||||
err = remote()->transact(
|
||||
BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
|
||||
data, &reply);
|
||||
if (err != NO_ERROR) {
|
||||
LOGE("ISurfaceComposer::createDisplayEventConnection: error performing "
|
||||
"transaction: %s (%d)", strerror(-err), -err);
|
||||
return result;
|
||||
}
|
||||
result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
|
||||
@ -254,6 +280,12 @@ status_t BnSurfaceComposer::onTransact(
|
||||
int32_t result = authenticateSurfaceTexture(surfaceTexture) ? 1 : 0;
|
||||
reply->writeInt32(result);
|
||||
} break;
|
||||
case CREATE_DISPLAY_EVENT_CONNECTION: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
sp<IDisplayEventConnection> connection(createDisplayEventConnection());
|
||||
reply->writeStrongBinder(connection->asBinder());
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
default:
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
@ -2,19 +2,22 @@ LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
Layer.cpp \
|
||||
LayerBase.cpp \
|
||||
LayerDim.cpp \
|
||||
LayerScreenshot.cpp \
|
||||
DdmConnection.cpp \
|
||||
DisplayHardware/DisplayHardware.cpp \
|
||||
EventThread.cpp \
|
||||
Layer.cpp \
|
||||
LayerBase.cpp \
|
||||
LayerDim.cpp \
|
||||
LayerScreenshot.cpp \
|
||||
DdmConnection.cpp \
|
||||
DisplayHardware/DisplayHardware.cpp \
|
||||
DisplayHardware/DisplayHardwareBase.cpp \
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
GLExtensions.cpp \
|
||||
MessageQueue.cpp \
|
||||
SurfaceFlinger.cpp \
|
||||
SurfaceTextureLayer.cpp \
|
||||
Transform.cpp \
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
DisplayHardware/VSyncBarrier.cpp \
|
||||
DisplayEventConnection.cpp \
|
||||
GLExtensions.cpp \
|
||||
MessageQueue.cpp \
|
||||
SurfaceFlinger.cpp \
|
||||
SurfaceTextureLayer.cpp \
|
||||
Transform.cpp \
|
||||
|
||||
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
|
||||
|
62
services/surfaceflinger/DisplayEventConnection.cpp
Normal file
62
services/surfaceflinger/DisplayEventConnection.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
#include <gui/BitTube.h>
|
||||
#include <gui/DisplayEventReceiver.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "DisplayEventConnection.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
DisplayEventConnection::DisplayEventConnection(
|
||||
const sp<SurfaceFlinger>& flinger)
|
||||
: mFlinger(flinger), mChannel(new BitTube())
|
||||
{
|
||||
}
|
||||
|
||||
DisplayEventConnection::~DisplayEventConnection() {
|
||||
mFlinger->cleanupDisplayEventConnection(this);
|
||||
}
|
||||
|
||||
void DisplayEventConnection::onFirstRef() {
|
||||
// nothing to do here for now.
|
||||
}
|
||||
|
||||
sp<BitTube> DisplayEventConnection::getDataChannel() const {
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
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
|
60
services/surfaceflinger/DisplayEventConnection.h
Normal file
60
services/surfaceflinger/DisplayEventConnection.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H
|
||||
#define ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <gui/DisplayEventReceiver.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class BitTube;
|
||||
class SurfaceFlinger;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class DisplayEventConnection : public BnDisplayEventConnection {
|
||||
public:
|
||||
DisplayEventConnection(const sp<SurfaceFlinger>& flinger);
|
||||
|
||||
status_t postEvent(const DisplayEventReceiver::Event& event);
|
||||
|
||||
private:
|
||||
virtual ~DisplayEventConnection();
|
||||
virtual void onFirstRef();
|
||||
virtual sp<BitTube> getDataChannel() const;
|
||||
|
||||
sp<SurfaceFlinger> const mFlinger;
|
||||
sp<BitTube> const mChannel;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif /* ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H */
|
@ -140,6 +140,7 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
mDpiX = mNativeWindow->xdpi;
|
||||
mDpiY = mNativeWindow->ydpi;
|
||||
mRefreshRate = fbDev->fps;
|
||||
mNextFakeVSync = 0;
|
||||
|
||||
|
||||
/* FIXME: this is a temporary HACK until we are able to report the refresh rate
|
||||
@ -152,6 +153,8 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
#warning "refresh rate set via makefile to REFRESH_RATE"
|
||||
#endif
|
||||
|
||||
mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
|
||||
|
||||
EGLint w, h, dummy;
|
||||
EGLint numConfigs=0;
|
||||
EGLSurface surface;
|
||||
@ -346,6 +349,37 @@ uint32_t DisplayHardware::getPageFlipCount() const {
|
||||
return mPageFlipCount;
|
||||
}
|
||||
|
||||
// this needs to be thread safe
|
||||
nsecs_t DisplayHardware::waitForVSync() const {
|
||||
nsecs_t timestamp;
|
||||
if (mVSync.wait(×tamp) < 0) {
|
||||
// vsync not supported!
|
||||
usleep( getDelayToNextVSyncUs(×tamp) );
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const {
|
||||
Mutex::Autolock _l(mFakeVSyncMutex);
|
||||
const nsecs_t period = mRefreshPeriod;
|
||||
const nsecs_t now = systemTime(CLOCK_MONOTONIC);
|
||||
nsecs_t next_vsync = mNextFakeVSync;
|
||||
nsecs_t sleep = next_vsync - now;
|
||||
if (sleep < 0) {
|
||||
// we missed, find where the next vsync should be
|
||||
sleep = (period - ((now - next_vsync) % period));
|
||||
next_vsync = now + sleep;
|
||||
}
|
||||
mNextFakeVSync = next_vsync + period;
|
||||
timestamp[0] = next_vsync;
|
||||
|
||||
// round to next microsecond
|
||||
int32_t sleep_us = (sleep + 999LL) / 1000LL;
|
||||
|
||||
// guaranteed to be > 0
|
||||
return sleep_us;
|
||||
}
|
||||
|
||||
status_t DisplayHardware::compositionComplete() const {
|
||||
return mNativeWindow->compositionComplete();
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "GLExtensions.h"
|
||||
|
||||
#include "DisplayHardware/DisplayHardwareBase.h"
|
||||
#include "DisplayHardware/VSyncBarrier.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
@ -74,6 +75,9 @@ public:
|
||||
uint32_t getMaxTextureSize() const;
|
||||
uint32_t getMaxViewportDims() const;
|
||||
|
||||
// waits for the next vsync and returns the timestamp of when it happened
|
||||
nsecs_t waitForVSync() const;
|
||||
|
||||
uint32_t getPageFlipCount() const;
|
||||
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
||||
|
||||
@ -95,6 +99,7 @@ public:
|
||||
private:
|
||||
void init(uint32_t displayIndex) __attribute__((noinline));
|
||||
void fini() __attribute__((noinline));
|
||||
int32_t getDelayToNextVSyncUs(nsecs_t* timestamp) const;
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
EGLDisplay mDisplay;
|
||||
@ -112,7 +117,12 @@ private:
|
||||
mutable uint32_t mPageFlipCount;
|
||||
GLint mMaxViewportDims[2];
|
||||
GLint mMaxTextureSize;
|
||||
|
||||
VSyncBarrier mVSync;
|
||||
|
||||
mutable Mutex mFakeVSyncMutex;
|
||||
mutable nsecs_t mNextFakeVSync;
|
||||
nsecs_t mRefreshPeriod;
|
||||
|
||||
HWComposer* mHwc;
|
||||
|
||||
sp<FramebufferNativeWindow> mNativeWindow;
|
||||
|
81
services/surfaceflinger/DisplayHardware/VSyncBarrier.cpp
Normal file
81
services/surfaceflinger/DisplayHardware/VSyncBarrier.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include "DisplayHardware/VSyncBarrier.h"
|
||||
|
||||
#ifndef FBIO_WAITFORVSYNC
|
||||
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
VSyncBarrier::VSyncBarrier() : mFd(-EINVAL) {
|
||||
#if HAS_WAITFORVSYNC
|
||||
mFd = open("/dev/graphics/fb0", O_RDWR);
|
||||
if (mFd < 0) {
|
||||
mFd = -errno;
|
||||
}
|
||||
// try to see if FBIO_WAITFORVSYNC is supported
|
||||
uint32_t crt = 0;
|
||||
int err = ioctl(mFd, FBIO_WAITFORVSYNC, &crt);
|
||||
if (err < 0) {
|
||||
close(mFd);
|
||||
mFd = -EINVAL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
VSyncBarrier::~VSyncBarrier() {
|
||||
if (mFd >= 0) {
|
||||
close(mFd);
|
||||
}
|
||||
}
|
||||
|
||||
status_t VSyncBarrier::initCheck() const {
|
||||
return mFd < 0 ? mFd : status_t(NO_ERROR);
|
||||
}
|
||||
|
||||
// this must be thread-safe
|
||||
status_t VSyncBarrier::wait(nsecs_t* timestamp) const {
|
||||
if (mFd < 0) {
|
||||
return mFd;
|
||||
}
|
||||
|
||||
int err;
|
||||
uint32_t crt = 0;
|
||||
do {
|
||||
err = ioctl(mFd, FBIO_WAITFORVSYNC, &crt);
|
||||
} while (err<0 && errno==EINTR);
|
||||
if (err < 0) {
|
||||
return -errno;
|
||||
}
|
||||
// ideally this would come from the driver
|
||||
timestamp[0] = systemTime();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
41
services/surfaceflinger/DisplayHardware/VSyncBarrier.h
Normal file
41
services/surfaceflinger/DisplayHardware/VSyncBarrier.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_SURFACE_FLINGER_VSYNCBARRIER_H_
|
||||
#define ANDROID_SURFACE_FLINGER_VSYNCBARRIER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class VSyncBarrier {
|
||||
int mFd;
|
||||
public:
|
||||
VSyncBarrier();
|
||||
~VSyncBarrier();
|
||||
status_t initCheck() const;
|
||||
status_t wait(nsecs_t* timestamp) const;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif /* ANDROID_SURFACE_FLINGER_VSYNCBARRIER_H_ */
|
129
services/surfaceflinger/EventThread.cpp
Normal file
129
services/surfaceflinger/EventThread.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
#include <gui/DisplayEventReceiver.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "DisplayEventConnection.h"
|
||||
#include "EventThread.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
|
||||
: mFlinger(flinger),
|
||||
mHw(flinger->graphicPlane(0).displayHardware()),
|
||||
mDeliveredEvents(0)
|
||||
{
|
||||
}
|
||||
|
||||
void EventThread::onFirstRef() {
|
||||
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
|
||||
}
|
||||
|
||||
status_t EventThread::registerDisplayEventConnection(
|
||||
const sp<DisplayEventConnection>& connection) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mDisplayEventConnections.add(connection);
|
||||
mCondition.signal();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t EventThread::unregisterDisplayEventConnection(
|
||||
const wp<DisplayEventConnection>& connection) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mDisplayEventConnections.remove(connection);
|
||||
mCondition.signal();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool EventThread::threadLoop() {
|
||||
|
||||
nsecs_t timestamp;
|
||||
Mutex::Autolock _l(mLock);
|
||||
do {
|
||||
// wait for listeners
|
||||
while (!mDisplayEventConnections.size()) {
|
||||
mCondition.wait(mLock);
|
||||
}
|
||||
|
||||
// wait for vsync
|
||||
mLock.unlock();
|
||||
timestamp = mHw.waitForVSync();
|
||||
mLock.lock();
|
||||
|
||||
// make sure we still have some listeners
|
||||
} while (!mDisplayEventConnections.size());
|
||||
|
||||
|
||||
// dispatch vsync events to listeners...
|
||||
mDeliveredEvents++;
|
||||
const size_t count = mDisplayEventConnections.size();
|
||||
|
||||
DisplayEventReceiver::Event vsync;
|
||||
vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
|
||||
vsync.header.timestamp = timestamp;
|
||||
vsync.vsync.count = mDeliveredEvents;
|
||||
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
sp<DisplayEventConnection> conn(mDisplayEventConnections.itemAt(i).promote());
|
||||
// make sure the connection didn't die
|
||||
if (conn != NULL) {
|
||||
status_t err = conn->postEvent(vsync);
|
||||
if (err == -EAGAIN || err == -EWOULDBLOCK) {
|
||||
// The destination doesn't accept events anymore, it's probably
|
||||
// full. For now, we just drop the events on the floor.
|
||||
// Note that some events cannot be dropped and would have to be
|
||||
// re-sent later. Right-now we don't have the ability to do
|
||||
// this, but it doesn't matter for VSYNC.
|
||||
} else if (err < 0) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
status_t EventThread::readyToRun() {
|
||||
LOGI("EventThread ready to run.");
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
|
||||
Mutex::Autolock _l(mLock);
|
||||
result.append("VSYNC state:\n");
|
||||
snprintf(buffer, SIZE, " numListeners=%u, events-delivered: %u\n",
|
||||
mDisplayEventConnections.size(), mDeliveredEvents);
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
79
services/surfaceflinger/EventThread.h
Normal file
79
services/surfaceflinger/EventThread.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_SURFACE_FLINGER_EVENT_THREAD_H
|
||||
#define ANDROID_SURFACE_FLINGER_EVENT_THREAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/SortedVector.h>
|
||||
|
||||
#include "DisplayEventConnection.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class SurfaceFlinger;
|
||||
class DisplayHardware;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class EventThread : public Thread {
|
||||
friend class DisplayEventConnection;
|
||||
|
||||
public:
|
||||
EventThread(const sp<SurfaceFlinger>& flinger);
|
||||
|
||||
status_t registerDisplayEventConnection(
|
||||
const sp<DisplayEventConnection>& connection);
|
||||
|
||||
status_t unregisterDisplayEventConnection(
|
||||
const wp<DisplayEventConnection>& connection);
|
||||
|
||||
void dump(String8& result, char* buffer, size_t SIZE) const;
|
||||
|
||||
private:
|
||||
virtual bool threadLoop();
|
||||
virtual status_t readyToRun();
|
||||
virtual void onFirstRef();
|
||||
|
||||
// constants
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
const DisplayHardware& mHw;
|
||||
|
||||
mutable Mutex mLock;
|
||||
mutable Condition mCondition;
|
||||
|
||||
// protected by mLock
|
||||
SortedVector<wp<DisplayEventConnection> > mDisplayEventConnections;
|
||||
size_t mDeliveredEvents;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif /* ANDROID_SURFACE_FLINGER_EVENT_THREAD_H */
|
@ -34,6 +34,8 @@
|
||||
#include <binder/MemoryHeapBase.h>
|
||||
#include <binder/PermissionCache.h>
|
||||
|
||||
#include <gui/IDisplayEventConnection.h>
|
||||
|
||||
#include <utils/String8.h>
|
||||
#include <utils/String16.h>
|
||||
#include <utils/StopWatch.h>
|
||||
@ -46,6 +48,8 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "clz.h"
|
||||
#include "DisplayEventConnection.h"
|
||||
#include "EventThread.h"
|
||||
#include "GLExtensions.h"
|
||||
#include "DdmConnection.h"
|
||||
#include "Layer.h"
|
||||
@ -293,12 +297,16 @@ status_t SurfaceFlinger::readyToRun()
|
||||
// put the origin in the left-bottom corner
|
||||
glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
|
||||
|
||||
mReadyToRunBarrier.open();
|
||||
|
||||
// start the EventThread
|
||||
mEventThread = new EventThread(this);
|
||||
|
||||
/*
|
||||
* We're now ready to accept clients...
|
||||
*/
|
||||
|
||||
mReadyToRunBarrier.open();
|
||||
|
||||
// start boot animation
|
||||
property_set("ctl.start", "bootanim");
|
||||
|
||||
@ -319,6 +327,22 @@ 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(
|
||||
const sp<ISurfaceTexture>& surfaceTexture) const {
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
@ -360,20 +384,17 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
|
||||
return false;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime, uint32_t flags)
|
||||
{
|
||||
return mEventQueue.postMessage(msg, reltime, flags);
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
|
||||
sp<DisplayEventConnection> result(new DisplayEventConnection(this));
|
||||
mEventThread->registerDisplayEventConnection(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime, uint32_t flags)
|
||||
{
|
||||
status_t res = mEventQueue.postMessage(msg, reltime, flags);
|
||||
if (res == NO_ERROR) {
|
||||
msg->wait();
|
||||
}
|
||||
return res;
|
||||
void SurfaceFlinger::cleanupDisplayEventConnection(
|
||||
const wp<DisplayEventConnection>& connection) {
|
||||
mEventThread->unregisterDisplayEventConnection(connection);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -432,7 +453,7 @@ bool SurfaceFlinger::threadLoop()
|
||||
} else {
|
||||
// pretend we did the post
|
||||
hw.compositionComplete();
|
||||
usleep(16667); // 60 fps period
|
||||
hw.waitForVSync();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1571,10 +1592,17 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* VSYNC state
|
||||
*/
|
||||
mEventThread->dump(result, buffer, SIZE);
|
||||
|
||||
/*
|
||||
* Dump HWComposer state
|
||||
*/
|
||||
HWComposer& hwc(hw.getHwComposer());
|
||||
snprintf(buffer, SIZE, "h/w composer state:\n");
|
||||
result.append(buffer);
|
||||
snprintf(buffer, SIZE, " h/w composer %s and %s\n",
|
||||
hwc.initCheck()==NO_ERROR ? "present" : "not present",
|
||||
(mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
|
||||
|
@ -46,6 +46,8 @@ namespace android {
|
||||
|
||||
class Client;
|
||||
class DisplayHardware;
|
||||
class DisplayEventConnection;
|
||||
class EventThread;
|
||||
class Layer;
|
||||
class LayerDim;
|
||||
class LayerScreenshot;
|
||||
@ -171,6 +173,7 @@ public:
|
||||
int orientation, uint32_t flags);
|
||||
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
|
||||
virtual bool authenticateSurfaceTexture(const sp<ISurfaceTexture>& surface) const;
|
||||
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
|
||||
|
||||
virtual status_t captureScreen(DisplayID dpy,
|
||||
sp<IMemoryHeap>* heap,
|
||||
@ -222,6 +225,7 @@ private:
|
||||
|
||||
private:
|
||||
friend class Client;
|
||||
friend class DisplayEventConnection;
|
||||
friend class LayerBase;
|
||||
friend class LayerBaseClient;
|
||||
friend class Layer;
|
||||
@ -331,6 +335,9 @@ private:
|
||||
status_t electronBeamOffAnimationImplLocked();
|
||||
status_t electronBeamOnAnimationImplLocked();
|
||||
|
||||
void cleanupDisplayEventConnection(
|
||||
const wp<DisplayEventConnection>& connection);
|
||||
|
||||
void debugFlashRegions();
|
||||
void debugShowFPS() const;
|
||||
void drawWormhole() const;
|
||||
@ -361,6 +368,7 @@ private:
|
||||
GLuint mWormholeTexName;
|
||||
GLuint mProtectedTexName;
|
||||
nsecs_t mBootTime;
|
||||
sp<EventThread> mEventThread;
|
||||
|
||||
// Can only accessed from the main thread, these members
|
||||
// don't need synchronization
|
||||
|
18
services/surfaceflinger/tests/vsync/Android.mk
Normal file
18
services/surfaceflinger/tests/vsync/Android.mk
Normal file
@ -0,0 +1,18 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
vsync.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libutils \
|
||||
libbinder \
|
||||
libui \
|
||||
libgui
|
||||
|
||||
LOCAL_MODULE:= test-vsync-events
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
81
services/surfaceflinger/tests/vsync/vsync.cpp
Normal file
81
services/surfaceflinger/tests/vsync/vsync.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gui/DisplayEventReceiver.h>
|
||||
#include <utils/Looper.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
int receiver(int fd, int events, void* data)
|
||||
{
|
||||
DisplayEventReceiver* q = (DisplayEventReceiver*)data;
|
||||
|
||||
ssize_t n;
|
||||
DisplayEventReceiver::Event buffer[1];
|
||||
|
||||
static nsecs_t oldTimeStamp = 0;
|
||||
|
||||
while ((n = q->getEvents(buffer, 1)) > 0) {
|
||||
for (int i=0 ; i<n ; i++) {
|
||||
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
|
||||
printf("event vsync: count=%d\t", buffer[i].vsync.count);
|
||||
}
|
||||
if (oldTimeStamp) {
|
||||
float t = float(buffer[i].header.timestamp - oldTimeStamp) / s2ns(1);
|
||||
printf("%f ms (%f Hz)\n", t*1000, 1.0/t);
|
||||
}
|
||||
oldTimeStamp = buffer[i].header.timestamp;
|
||||
}
|
||||
}
|
||||
if (n<0) {
|
||||
printf("error reading events (%s)\n", strerror(-n));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
DisplayEventReceiver myDisplayEvent;
|
||||
|
||||
|
||||
sp<Looper> loop = new Looper(false);
|
||||
loop->addFd(myDisplayEvent.getFd(), 0, ALOOPER_EVENT_INPUT, receiver,
|
||||
&myDisplayEvent);
|
||||
|
||||
do {
|
||||
//printf("about to poll...\n");
|
||||
int32_t ret = loop->pollOnce(-1);
|
||||
switch (ret) {
|
||||
case ALOOPER_POLL_WAKE:
|
||||
//("ALOOPER_POLL_WAKE\n");
|
||||
break;
|
||||
case ALOOPER_POLL_CALLBACK:
|
||||
//("ALOOPER_POLL_CALLBACK\n");
|
||||
break;
|
||||
case ALOOPER_POLL_TIMEOUT:
|
||||
printf("ALOOPER_POLL_TIMEOUT\n");
|
||||
break;
|
||||
case ALOOPER_POLL_ERROR:
|
||||
printf("ALOOPER_POLL_TIMEOUT\n");
|
||||
break;
|
||||
default:
|
||||
printf("ugh? poll returned %d\n", ret);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
14
services/surfaceflinger/tests/waitforvsync/Android.mk
Normal file
14
services/surfaceflinger/tests/waitforvsync/Android.mk
Normal file
@ -0,0 +1,14 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
waitforvsync.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
|
||||
LOCAL_MODULE:= test-waitforvsync
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
45
services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
Normal file
45
services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef FBIO_WAITFORVSYNC
|
||||
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int fd = open("/dev/graphics/fb0", O_RDWR);
|
||||
if (fd >= 0) {
|
||||
do {
|
||||
uint32_t crt = 0;
|
||||
int err = ioctl(fd, FBIO_WAITFORVSYNC, &crt);
|
||||
if (err < 0) {
|
||||
printf("FBIO_WAITFORVSYNC error: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user