The Hardware Composer handles three types of sync fences:
Acquire fences are passed along with input buffers to the setLayerBuffer and setClientTarget calls. These represent a pending write into the buffer and must signal before the SurfaceFlinger or the HWC attempts to read from the associated buffer to perform composition.
Release fences are retrieved after the call to presentDisplay using the getReleaseFences call. These represent a pending read from the previous buffer on the same layer. A release fence signals when the HWC is no longer using the previous buffer because the current buffer has replaced the previous buffer on the display. Release fences are passed back to the app along with the previous buffers that will be replaced during the current composition. The app must wait until a release fence signals before writing new contents into the buffer that was returned to them.
Present fences are returned, one per frame, as part of the call to presentDisplay. Present fences represent when the composition of this frame has completed, or alternately, when the composition result of the prior frame is no longer needed. For physical displays, presentDisplay returns present fences when the current frame appears on the screen. After present fences are returned, it’s safe to write to the SurfaceFlinger target buffer again, if applicable. For virtual displays, present fences are returned when it’s safe to read from the output buffer.
// setDesiredPresentTime sets the time at which the current frame // should be presented to the user under ideal (i.e. zero latency) // conditions. //理想条件下(即零延迟)呈现给用户的时间点。 voidsetDesiredPresentTime(nsecs_t desiredPresentTime);
// setFrameReadyTime sets the time at which the current frame became ready // to be presented to the user. For example, if the frame contents is // being written to memory by some asynchronous hardware, this would be // the time at which those writes completed. voidsetFrameReadyTime(nsecs_t readyTime);
// setFrameReadyFence sets the fence that is used to get the time at which // the current frame became ready to be presented to the user. voidsetFrameReadyFence(std::shared_ptr<FenceTime>&& readyFence);
// setActualPresentTime sets the timestamp at which the current frame became // visible to the user. voidsetActualPresentTime(nsecs_t displayTime);
// setActualPresentFence sets the fence that is used to get the time // at which the current frame became visible to the user. voidsetActualPresentFence(const std::shared_ptr<FenceTime>& fence);
...... std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { //关键点2:设置frameReadyFence mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { //纯软件绘制才走这里,frameReadyTime和desiredPresentTime就一样了 // There was no fence for this frame, so assume that it was ready // to be presented at the desired present time. mFrameTracker.setFrameReadyTime(desiredPresentTime); }
// Hang onto the pointer so that it isn't freed in the call to // releaseBufferLocked() if we're in shared buffer mode and both buffers are // the same.
if (mAbandoned) { BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!"); return NO_INIT; }
BufferItem item;
// Acquire the next buffer. // In asynchronous mode the list is guaranteed to be one buffer // deep, while in synchronous mode we use the oldest buffer. status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber); if (err != NO_ERROR) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { err = NO_ERROR; } elseif (err == BufferQueue::PRESENT_LATER) { // return the error, without logging } else { BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err); } return err; }
if (autoRefresh) { *autoRefresh = item.mAutoRefresh; }
if (queuedBuffer) { *queuedBuffer = item.mQueuedBuffer; }
// We call the rejecter here, in case the caller has a reason to // not accept this buffer. This is used by SurfaceFlinger to // reject buffers which have the wrong size int slot = item.mSlot; if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) { releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer); return BUFFER_REJECTED; }
// mTimestamp is the current timestamp for this buffer slot. This gets // to set by queueBuffer each time this slot is queued. This value // is guaranteed to be monotonically increasing for each newly // acquired buffer. //从这里的注释已经可以知道它是queueBuffer时的时间戳 int64_t mTimestamp;
// The std::shared_ptr<FenceTime> wrapper around mFence. std::shared_ptr<FenceTime> mFenceTime{FenceTime::NO_FENCE};
ATRACE_INT(mCore->mConsumerName.string(), static_cast<int32_t>(mCore->mQueue.size())); #ifndef NO_BINDER mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size()); #endif // Take a ticket for the callback functions callbackTicket = mNextCallbackTicket++;
// timestamp - a monotonically increasing value in nanoseconds // isAutoTimestamp - if the timestamp was synthesized at queue time // dataSpace - description of the contents, interpretation depends on format // crop - a crop rectangle that's used as a hint to the consumer // scalingMode - a set of flags from NATIVE_WINDOW_SCALING_* in <window.h> // transform - a set of flags from NATIVE_WINDOW_TRANSFORM_* in <window.h>
// acquireFenceTime相关 // fence - a fence that the consumer must wait on before reading the buffer, // set this to Fence::NO_FENCE if the buffer is ready immediately
// sticky - the sticky transform set in Surface (only used by the LEGACY // camera mode). // getFrameTimestamps - whether or not the latest frame timestamps // should be retrieved from the consumer. // slot - the slot index to queue. This is used only by queueBuffers(). // queueBuffer() ignores this value and uses the argument `slot` // instead. inlineQueueBufferInput(int64_t _timestamp, bool _isAutoTimestamp, android_dataspace _dataSpace, const Rect& _crop, int _scalingMode, uint32_t _transform, const sp<Fence>& _fence, uint32_t _sticky = 0, bool _getFrameTimestamps = false, int _slot = -1) : timestamp(_timestamp), isAutoTimestamp(_isAutoTimestamp), dataSpace(_dataSpace), crop(_crop), scalingMode(_scalingMode), transform(_transform), stickyTransform(_sticky), fence(_fence), surfaceDamage(), getFrameTimestamps(_getFrameTimestamps), slot(_slot) { }