Merge "Add support for timestamps into SurfaceTexture."
This commit is contained in:
commit
edc5ac145b
include
gui
surfaceflinger
ui/egl
libs
@ -62,8 +62,11 @@ public:
|
||||
// contents of the buffer associated with slot and transfers ownership of
|
||||
// that slot back to the server. It is not valid to call queueBuffer on a
|
||||
// slot that is not owned by the client or one for which a buffer associated
|
||||
// via requestBuffer.
|
||||
virtual status_t queueBuffer(int slot) = 0;
|
||||
// via requestBuffer. In addition, a timestamp must be provided by the
|
||||
// client for this buffer. The timestamp is measured in nanoseconds, and
|
||||
// must be monotonically increasing. Its other properties (zero point, etc)
|
||||
// are client-dependent, and should be documented by the client.
|
||||
virtual status_t queueBuffer(int slot, int64_t timestamp) = 0;
|
||||
|
||||
// cancelBuffer indicates that the client does not wish to fill in the
|
||||
// buffer associated with slot and transfers ownership of the slot back to
|
||||
|
@ -66,7 +66,12 @@ public:
|
||||
// unmodified.
|
||||
virtual status_t dequeueBuffer(int *buf);
|
||||
|
||||
virtual status_t queueBuffer(int buf);
|
||||
// queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
|
||||
// timestamp must be provided for the buffer. The timestamp is in
|
||||
// nanoseconds, and must be monotonically increasing. Its other semantics
|
||||
// (zero point, etc) are client-dependent and should be documented by the
|
||||
// client.
|
||||
virtual status_t queueBuffer(int buf, int64_t timestamp);
|
||||
virtual void cancelBuffer(int buf);
|
||||
virtual status_t setCrop(const Rect& reg);
|
||||
virtual status_t setTransform(uint32_t transform);
|
||||
@ -98,6 +103,14 @@ public:
|
||||
// functions.
|
||||
void getTransformMatrix(float mtx[16]);
|
||||
|
||||
// getTimestamp retrieves the timestamp associated with the texture image
|
||||
// set by the most recent call to updateTexImage.
|
||||
//
|
||||
// The timestamp is in nanoseconds, and is monotonically increasing. Its
|
||||
// other semantics (zero point, etc) are source-dependent and should be
|
||||
// documented by the source.
|
||||
int64_t getTimestamp();
|
||||
|
||||
// setFrameAvailableListener sets the listener object that will be notified
|
||||
// when a new frame becomes available.
|
||||
void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
|
||||
@ -172,6 +185,10 @@ private:
|
||||
// gets set to mLastQueuedTransform each time updateTexImage is called.
|
||||
uint32_t mCurrentTransform;
|
||||
|
||||
// mCurrentTimestamp is the timestamp for the current texture. It
|
||||
// gets set to mLastQueuedTimestamp each time updateTexImage is called.
|
||||
int64_t mCurrentTimestamp;
|
||||
|
||||
// mLastQueued is the buffer slot index of the most recently enqueued buffer.
|
||||
// At construction time it is initialized to INVALID_BUFFER_SLOT, and is
|
||||
// updated each time queueBuffer is called.
|
||||
@ -187,6 +204,10 @@ private:
|
||||
// queueBuffer gets called.
|
||||
uint32_t mLastQueuedTransform;
|
||||
|
||||
// mLastQueuedTimestamp is the timestamp for the buffer that was most
|
||||
// recently queued. This gets set by queueBuffer.
|
||||
int64_t mLastQueuedTimestamp;
|
||||
|
||||
// mNextCrop is the crop rectangle that will be used for the next buffer
|
||||
// that gets queued. It is set by calling setCrop.
|
||||
Rect mNextCrop;
|
||||
|
@ -63,6 +63,7 @@ private:
|
||||
int dispatchSetBufferCount(va_list args);
|
||||
int dispatchSetBuffersGeometry(va_list args);
|
||||
int dispatchSetBuffersTransform(va_list args);
|
||||
int dispatchSetBuffersTimestamp(va_list args);
|
||||
int dispatchSetCrop(va_list args);
|
||||
int dispatchSetUsage(va_list args);
|
||||
|
||||
@ -71,6 +72,7 @@ private:
|
||||
int setBufferCount(int bufferCount);
|
||||
int setBuffersGeometry(int w, int h, int format);
|
||||
int setBuffersTransform(int transform);
|
||||
int setBuffersTimestamp(int64_t timestamp);
|
||||
int setCrop(Rect const* rect);
|
||||
int setUsage(uint32_t reqUsage);
|
||||
|
||||
@ -114,6 +116,11 @@ private:
|
||||
// at the next deuque operation. It is initialized to 0.
|
||||
uint32_t mReqUsage;
|
||||
|
||||
// mTimestamp is the timestamp that will be used for the next buffer queue
|
||||
// operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
|
||||
// a timestamp is auto-generated when queueBuffer is called.
|
||||
int64_t mTimestamp;
|
||||
|
||||
// mMutex is the mutex used to prevent concurrent access to the member
|
||||
// variables of SurfaceTexture objects. It must be locked whenever the
|
||||
// member variables are accessed.
|
||||
|
@ -226,7 +226,8 @@ private:
|
||||
int dispatch_set_buffer_count(va_list args);
|
||||
int dispatch_set_buffers_geometry(va_list args);
|
||||
int dispatch_set_buffers_transform(va_list args);
|
||||
|
||||
int dispatch_set_buffers_timestamp(va_list args);
|
||||
|
||||
void setUsage(uint32_t reqUsage);
|
||||
int connect(int api);
|
||||
int disconnect(int api);
|
||||
@ -234,6 +235,7 @@ private:
|
||||
int setBufferCount(int bufferCount);
|
||||
int setBuffersGeometry(int w, int h, int format);
|
||||
int setBuffersTransform(int transform);
|
||||
int setBuffersTimestamp(int64_t timestamp);
|
||||
|
||||
/*
|
||||
* private stuff...
|
||||
|
@ -57,7 +57,7 @@ typedef struct android_native_base_t
|
||||
{
|
||||
/* a magic value defined by the actual EGL native type */
|
||||
int magic;
|
||||
|
||||
|
||||
/* the sizeof() of the actual EGL native type */
|
||||
int version;
|
||||
|
||||
@ -129,6 +129,7 @@ enum {
|
||||
NATIVE_WINDOW_SET_BUFFER_COUNT,
|
||||
NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
|
||||
NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
|
||||
NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
|
||||
};
|
||||
|
||||
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
|
||||
@ -157,7 +158,15 @@ enum {
|
||||
NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, // SurfaceTextureClient
|
||||
};
|
||||
|
||||
struct ANativeWindow
|
||||
/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
|
||||
*
|
||||
* Special timestamp value to indicate that timestamps should be auto-generated
|
||||
* by the native window when queueBuffer is called. This is equal to INT64_MIN,
|
||||
* defined directly to avoid problems with C99/C++ inclusion of stdint.h.
|
||||
*/
|
||||
const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
|
||||
|
||||
struct ANativeWindow
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
ANativeWindow()
|
||||
@ -262,7 +271,8 @@ struct ANativeWindow
|
||||
* NATIVE_WINDOW_SET_BUFFER_COUNT
|
||||
* NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
|
||||
* NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
|
||||
*
|
||||
* NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
|
||||
*
|
||||
*/
|
||||
|
||||
int (*perform)(struct ANativeWindow* window,
|
||||
@ -389,6 +399,22 @@ static inline int native_window_set_buffers_transform(
|
||||
transform);
|
||||
}
|
||||
|
||||
/*
|
||||
* native_window_set_buffers_timestamp(..., int64_t timestamp)
|
||||
* All buffers queued after this call will be associated with the timestamp
|
||||
* parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
|
||||
* (the default), timestamps will be generated automatically when queueBuffer is
|
||||
* called. The timestamp is measured in nanoseconds, and must be monotonically
|
||||
* increasing.
|
||||
*/
|
||||
static inline int native_window_set_buffers_timestamp(
|
||||
ANativeWindow* window,
|
||||
int64_t timestamp)
|
||||
{
|
||||
return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* FIXME: this is legacy for pixmaps */
|
||||
|
@ -88,10 +88,11 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual status_t queueBuffer(int buf) {
|
||||
virtual status_t queueBuffer(int buf, int64_t timestamp) {
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
|
||||
data.writeInt32(buf);
|
||||
data.writeInt64(timestamp);
|
||||
remote()->transact(QUEUE_BUFFER, data, &reply);
|
||||
status_t result = reply.readInt32();
|
||||
return result;
|
||||
@ -174,7 +175,8 @@ status_t BnSurfaceTexture::onTransact(
|
||||
case QUEUE_BUFFER: {
|
||||
CHECK_INTERFACE(ISurfaceTexture, data, reply);
|
||||
int buf = data.readInt32();
|
||||
status_t result = queueBuffer(buf);
|
||||
int64_t timestamp = data.readInt64();
|
||||
status_t result = queueBuffer(buf, timestamp);
|
||||
reply->writeInt32(result);
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
@ -196,7 +198,6 @@ status_t BnSurfaceTexture::onTransact(
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case SET_TRANSFORM: {
|
||||
Rect reg;
|
||||
CHECK_INTERFACE(ISurfaceTexture, data, reply);
|
||||
uint32_t transform = data.readInt32();
|
||||
status_t result = setTransform(transform);
|
||||
|
@ -76,9 +76,15 @@ static float mtxRot270[16] = {
|
||||
static void mtxMul(float out[16], const float a[16], const float b[16]);
|
||||
|
||||
SurfaceTexture::SurfaceTexture(GLuint tex) :
|
||||
mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
|
||||
mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT),
|
||||
mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) {
|
||||
mBufferCount(MIN_BUFFER_SLOTS),
|
||||
mCurrentTexture(INVALID_BUFFER_SLOT),
|
||||
mCurrentTransform(0),
|
||||
mCurrentTimestamp(0),
|
||||
mLastQueued(INVALID_BUFFER_SLOT),
|
||||
mLastQueuedTransform(0),
|
||||
mLastQueuedTimestamp(0),
|
||||
mNextTransform(0),
|
||||
mTexName(tex) {
|
||||
LOGV("SurfaceTexture::SurfaceTexture");
|
||||
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
|
||||
mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
|
||||
@ -153,7 +159,7 @@ status_t SurfaceTexture::dequeueBuffer(int *buf) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t SurfaceTexture::queueBuffer(int buf) {
|
||||
status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
|
||||
LOGV("SurfaceTexture::queueBuffer");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
if (buf < 0 || mBufferCount <= buf) {
|
||||
@ -172,6 +178,7 @@ status_t SurfaceTexture::queueBuffer(int buf) {
|
||||
mLastQueued = buf;
|
||||
mLastQueuedCrop = mNextCrop;
|
||||
mLastQueuedTransform = mNextTransform;
|
||||
mLastQueuedTimestamp = timestamp;
|
||||
if (mFrameAvailableListener != 0) {
|
||||
mFrameAvailableListener->onFrameAvailable();
|
||||
}
|
||||
@ -246,12 +253,13 @@ status_t SurfaceTexture::updateTexImage() {
|
||||
mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
|
||||
mCurrentCrop = mLastQueuedCrop;
|
||||
mCurrentTransform = mLastQueuedTransform;
|
||||
mCurrentTimestamp = mLastQueuedTimestamp;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
void SurfaceTexture::getTransformMatrix(float mtx[16]) {
|
||||
LOGV("SurfaceTexture::updateTexImage");
|
||||
LOGV("SurfaceTexture::getTransformMatrix");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
float xform[16];
|
||||
@ -342,6 +350,12 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) {
|
||||
mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
|
||||
}
|
||||
|
||||
nsecs_t SurfaceTexture::getTimestamp() {
|
||||
LOGV("SurfaceTexture::getTimestamp");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
return mCurrentTimestamp;
|
||||
}
|
||||
|
||||
void SurfaceTexture::setFrameAvailableListener(
|
||||
const sp<FrameAvailableListener>& l) {
|
||||
LOGV("SurfaceTexture::setFrameAvailableListener");
|
||||
|
@ -26,7 +26,8 @@ namespace android {
|
||||
SurfaceTextureClient::SurfaceTextureClient(
|
||||
const sp<ISurfaceTexture>& surfaceTexture):
|
||||
mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
|
||||
mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
|
||||
mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0),
|
||||
mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() {
|
||||
// Initialize the ANativeWindow function pointers.
|
||||
ANativeWindow::setSwapInterval = setSwapInterval;
|
||||
ANativeWindow::dequeueBuffer = dequeueBuffer;
|
||||
@ -135,9 +136,17 @@ int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
|
||||
int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
|
||||
LOGV("SurfaceTextureClient::queueBuffer");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
int64_t timestamp;
|
||||
if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
|
||||
timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",
|
||||
timestamp / 1000000.f);
|
||||
} else {
|
||||
timestamp = mTimestamp;
|
||||
}
|
||||
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
|
||||
if (mSlots[i]->handle == buffer->handle) {
|
||||
return mSurfaceTexture->queueBuffer(i);
|
||||
return mSurfaceTexture->queueBuffer(i, timestamp);
|
||||
}
|
||||
}
|
||||
LOGE("queueBuffer: unknown buffer queued");
|
||||
@ -196,6 +205,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
|
||||
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
|
||||
res = dispatchSetBuffersTransform(args);
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
|
||||
res = dispatchSetBuffersTimestamp(args);
|
||||
break;
|
||||
default:
|
||||
res = NAME_NOT_FOUND;
|
||||
break;
|
||||
@ -240,6 +252,11 @@ int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
|
||||
return setBuffersTransform(transform);
|
||||
}
|
||||
|
||||
int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
|
||||
int64_t timestamp = va_arg(args, int64_t);
|
||||
return setBuffersTimestamp(timestamp);
|
||||
}
|
||||
|
||||
int SurfaceTextureClient::connect(int api) {
|
||||
LOGV("SurfaceTextureClient::connect");
|
||||
// XXX: Implement this!
|
||||
@ -323,6 +340,14 @@ int SurfaceTextureClient::setBuffersTransform(int transform)
|
||||
return err;
|
||||
}
|
||||
|
||||
int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
|
||||
{
|
||||
LOGV("SurfaceTextureClient::setBuffersTimestamp");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
mTimestamp = timestamp;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void SurfaceTextureClient::freeAllBuffers() {
|
||||
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
|
||||
mSlots[i] = 0;
|
||||
|
@ -753,6 +753,9 @@ int Surface::perform(int operation, va_list args)
|
||||
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
|
||||
res = dispatch_set_buffers_transform( args );
|
||||
break;
|
||||
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
|
||||
res = dispatch_set_buffers_timestamp( args );
|
||||
break;
|
||||
default:
|
||||
res = NAME_NOT_FOUND;
|
||||
break;
|
||||
@ -792,6 +795,11 @@ int Surface::dispatch_set_buffers_transform(va_list args) {
|
||||
return setBuffersTransform(transform);
|
||||
}
|
||||
|
||||
int Surface::dispatch_set_buffers_timestamp(va_list args) {
|
||||
int64_t timestamp = va_arg(args, int64_t);
|
||||
return setBuffersTimestamp(timestamp);
|
||||
}
|
||||
|
||||
void Surface::setUsage(uint32_t reqUsage)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
@ -910,6 +918,13 @@ int Surface::setBuffersTransform(int transform)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int Surface::setBuffersTimestamp(int64_t timestamp)
|
||||
{
|
||||
// Surface doesn't really have anything meaningful to do with timestamps
|
||||
// so they'll just be dropped here.
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::getConnectedApi() const
|
||||
|
Loading…
Reference in New Issue
Block a user