// to set by queueBuffer each time this slot is queued.
int64_t mTimestamp;
+ // mIsAutoTimestamp indicates whether mTimestamp was generated
+ // automatically when the buffer was queued.
+ bool mIsAutoTimestamp;
+
// mFrameNumber is the number of the queued frame for this slot.
uint64_t mFrameNumber;
struct QueueBufferInput : public Flattenable<QueueBufferInput> {
friend class Flattenable<QueueBufferInput>;
inline QueueBufferInput(const Parcel& parcel);
- inline QueueBufferInput(int64_t timestamp,
+ inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
const Rect& crop, int scalingMode, uint32_t transform, bool async,
const sp<Fence>& fence)
- : timestamp(timestamp), crop(crop), scalingMode(scalingMode),
- transform(transform), async(async), fence(fence) { }
- inline void deflate(int64_t* outTimestamp, Rect* outCrop,
- int* outScalingMode, uint32_t* outTransform, bool* outAsync,
- sp<Fence>* outFence) const {
+ : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
+ scalingMode(scalingMode), transform(transform), async(async),
+ fence(fence) { }
+ inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
+ Rect* outCrop, int* outScalingMode, uint32_t* outTransform,
+ bool* outAsync, sp<Fence>* outFence) const {
*outTimestamp = timestamp;
+ *outIsAutoTimestamp = bool(isAutoTimestamp);
*outCrop = crop;
*outScalingMode = scalingMode;
*outTransform = transform;
private:
int64_t timestamp;
+ int isAutoTimestamp;
Rect crop;
int scalingMode;
uint32_t transform;
uint32_t transform;
int scalingMode;
int64_t timestamp;
+ bool isAutoTimestamp;
bool async;
sp<Fence> fence;
- input.deflate(×tamp, &crop, &scalingMode, &transform, &async, &fence);
+ input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
+ &async, &fence);
if (fence == NULL) {
ST_LOGE("queueBuffer: fence is NULL");
item.mTransform = transform;
item.mScalingMode = scalingMode;
item.mTimestamp = timestamp;
+ item.mIsAutoTimestamp = isAutoTimestamp;
item.mFrameNumber = mFrameCounter;
item.mBuf = buf;
item.mFence = fence;
//
// NOTE: code assumes monotonic time values from the system clock are
// positive.
- while (false && mQueue.size() > 1) {
+
+ // Start by checking to see if we can drop frames. We skip this check
+ // if the timestamps are being auto-generated by Surface -- if the
+ // app isn't generating timestamps explicitly, they probably don't
+ // want frames to be discarded based on them.
+ while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) {
// If entry[1] is timely, drop entry[0] (and repeat). We apply
// an additional criteria here: we only drop the earlier buffer if
// our desiredPresent falls within +/- 1 second of the expected
mTransform(0),
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mTimestamp(0),
+ mIsAutoTimestamp(false),
mFrameNumber(0),
mBuf(INVALID_BUFFER_SLOT),
mIsDroppable(false),
sizeof(mTransform) +
sizeof(mScalingMode) +
sizeof(mTimestamp) +
+ sizeof(mIsAutoTimestamp) +
sizeof(mFrameNumber) +
sizeof(mBuf) +
sizeof(mIsDroppable) +
FlattenableUtils::write(buffer, size, mTransform);
FlattenableUtils::write(buffer, size, mScalingMode);
FlattenableUtils::write(buffer, size, mTimestamp);
+ FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
FlattenableUtils::write(buffer, size, mFrameNumber);
FlattenableUtils::write(buffer, size, mBuf);
FlattenableUtils::write(buffer, size, mIsDroppable);
FlattenableUtils::read(buffer, size, mTransform);
FlattenableUtils::read(buffer, size, mScalingMode);
FlattenableUtils::read(buffer, size, mTimestamp);
+ FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
FlattenableUtils::read(buffer, size, mFrameNumber);
FlattenableUtils::read(buffer, size, mBuf);
FlattenableUtils::read(buffer, size, mIsDroppable);
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
return sizeof(timestamp)
+ + sizeof(isAutoTimestamp)
+ sizeof(crop)
+ sizeof(scalingMode)
+ sizeof(transform)
return NO_MEMORY;
}
FlattenableUtils::write(buffer, size, timestamp);
+ FlattenableUtils::write(buffer, size, isAutoTimestamp);
FlattenableUtils::write(buffer, size, crop);
FlattenableUtils::write(buffer, size, scalingMode);
FlattenableUtils::write(buffer, size, transform);
{
size_t minNeeded =
sizeof(timestamp)
+ + sizeof(isAutoTimestamp)
+ sizeof(crop)
+ sizeof(scalingMode)
+ sizeof(transform)
}
FlattenableUtils::read(buffer, size, timestamp);
+ FlattenableUtils::read(buffer, size, isAutoTimestamp);
FlattenableUtils::read(buffer, size, crop);
FlattenableUtils::read(buffer, size, scalingMode);
FlattenableUtils::read(buffer, size, transform);
ALOGV("Surface::queueBuffer");
Mutex::Autolock lock(mMutex);
int64_t timestamp;
+ bool isAutoTimestamp = false;
if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ isAutoTimestamp = true;
ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
timestamp / 1000000.f);
} else {
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output;
- IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode,
- mTransform, mSwapIntervalZero, fence);
+ IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
+ crop, mScalingMode, mTransform, mSwapIntervalZero, fence);
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
- QueueBufferInput(systemTime(),
+ QueueBufferInput(systemTime(), false,
Rect(mSinkBufferWidth, mSinkBufferHeight),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, outFence),
&qbo);
// Extract the GLES release fence for HWC to acquire
int64_t timestamp;
+ bool isAutoTimestamp;
Rect crop;
int scalingMode;
uint32_t transform;
bool async;
- input.deflate(×tamp, &crop, &scalingMode, &transform,
- &async, &mFbFence);
+ input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode,
+ &transform, &async, &mFbFence);
mFbProducerSlot = pslot;
}