- VR厂商为了让渲染出来的buffer快速上屏,采用了单缓冲机制,也就是EGL_SINGLE_BUFFER
但是单缓冲不需要swapbuffer,怎么呈现?
EGL有个扩展自动刷新上屏
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);
- 网上关于EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID的介绍机会没有
幸好有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.
解释下:此扩展适合对延迟要求比较高的应用,它向android合成器指示它应该在每次显示器刷新时执行合成,也就是说每次vync来了我都要合成。这减少了通知合成器的时间,但是这是有代价的,就算没有界面更新,他也会去合成
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 是个开关,指示合成器是否用前缓冲区渲染
现在看来自动刷新不一定好
- 跟踪下代码
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();
}
}