- VR廠商為了讓渲染出來(lái)的buffer快速上屏,采用了單緩沖機(jī)制,也就是EGL_SINGLE_BUFFER
但是單緩沖不需要swapbuffer,怎么呈現(xiàn)?
EGL有個(gè)擴(kuò)展自動(dòng)刷新上屏
EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID
- 配合使用就是
bool bRes = eglSurfaceAttrib(display, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
bRes = eglSurfaceAttrib(display, surface, EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID, 1);
- 網(wǎng)上關(guān)于EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID的介紹機(jī)會(huì)沒(méi)有
幸好有opengl的官方spec
1、 This extension is intended for latency-sensitive applications that are doing
front-buffer rendering. It allows them to indicate to the Android compositor
that it should perform composition every time the display refreshes. This
removes the overhead of having to notify the compositor that the window
surface has been updated, but it comes at the cost of doing potentially
unneeded composition work if the window surface has not been updated.
解釋下:此擴(kuò)展適合對(duì)延遲要求比較高的應(yīng)用,它向android合成器指示它應(yīng)該在每次顯示器刷新時(shí)執(zhí)行合成,也就是說(shuō)每次vync來(lái)了我都要合成。這減少了通知合成器的時(shí)間,但是這是有代價(jià)的,就算沒(méi)有界面更新,他也會(huì)去合成
2、If attribute is EGL_ANDROID_front_buffer_auto_refresh, then value specifies
whether to enable or disable auto-refresh in the Android compositor when
doing front-buffer rendering.
EGL_ANDROID_front_buffer_auto_refresh 是個(gè)開(kāi)關(guān),指示合成器是否用前緩沖區(qū)渲染
現(xiàn)在看來(lái)自動(dòng)刷新不一定好
- 跟蹤下代碼
frameworks/native/libs/nativewindow/include/system/window.h
* native_window_set_auto_refresh(..., autoRefresh)
* Enable/disable auto refresh when in shared buffer mode
*/
static inline int native_window_set_auto_refresh(
struct ANativeWindow* window,
bool autoRefresh)
{
return window->perform(window, NATIVE_WINDOW_SET_AUTO_REFRESH, autoRefresh);
}
frameworks/native/libs/gui/Surface.cpp
int Surface::perform(int operation, va_list args)
{ case NATIVE_WINDOW_SET_AUTO_REFRESH:
res = dispatchSetAutoRefresh(args);
break;
}
int Surface::dispatchSetAutoRefresh(va_list args) {
bool autoRefresh = va_arg(args, int);
return setAutoRefresh(autoRefresh);
}
int Surface::setAutoRefresh(bool autoRefresh) {
ATRACE_CALL();
ALOGV("Surface::setAutoRefresh (%d)", autoRefresh);
Mutex::Autolock lock(mMutex);
status_t err = mGraphicBufferProducer->setAutoRefresh(autoRefresh);
if (err == NO_ERROR) {
mAutoRefresh = autoRefresh;
}
ALOGE_IF(err, "IGraphicBufferProducer::setAutoRefresh(%d) returned %s",
autoRefresh, strerror(-err));
return err;
}
frameworks/native/libs/gui/IGraphicBufferProducer.cpp
case SET_AUTO_REFRESH: {
CHECK_INTERFACE(IGraphicBuffer, data, reply);
bool autoRefresh = data.readInt32();
status_t result = setAutoRefresh(autoRefresh);
reply->writeInt32(result);
return NO_ERROR;
}
frameworks/native/libs/gui/BufferHubProducer.cpp
status_t BufferQueueProducer::setAutoRefresh(bool autoRefresh) {
ATRACE_CALL();
BQ_LOGV("setAutoRefresh: %d", autoRefresh);
std::lock_guard<std::mutex> lock(mCore->mMutex);
mCore->mAutoRefresh = autoRefresh;
return NO_ERROR;
}
services/surfaceflinger/BufferLayer.cpp
bool BufferLayer::hasReadyFrame() const {
return hasFrameUpdate() || getSidebandStreamChanged() || getAutoRefresh();
}
services/surfaceflinger/SurfaceFlinger.cpp
handleMessageRefresh();
void SurfaceFlinger::preComposition()
{
ATRACE_CALL();
ALOGV("preComposition");
mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
bool needExtraInvalidate = false;
mDrawingState.traverseInZOrder([&](Layer* layer) {
if(!layer){
ALOGE("%s, found invalid layer!!!",__FUNCTION__);
return;
}
if (layer->onPreComposition(mRefreshStartTime)) {
needExtraInvalidate = true;
}
});
if (needExtraInvalidate) {
signalLayerUpdate();
}
}