c++打开log #define LOG_NDEBUG 0
1 SurfaceFlinger::init()->new HWComposer()
HWComposer 里面包含一个BitSet32 mAllocatedDisplayIDs 数据结构用于管理已经分配的display.
HWComposer初始化的过程中会默认创建NUM_BUILTIN_DISPLAYS(2)个设备ID.
据官方说法在设备注册热插拔函数后要立即收到主设备的热插拔事件.在设备的正常操作期间,除了主显示设备之外,仅可热插拔一个外部显示设备。
最多有三种类型设备分别如下
HWC_DISPLAY_PRIMARY = 0,
HWC_DISPLAY_EXTERNAL = 1, // HDMI, DP, etc.
HWC_DISPLAY_VIRTUAL = 2,
对于HWC_1.1版本之前的设备,这种设备直接使用FrameBuffer信息初始化HWC_DISPLAY_PRIMARY的DisplayData,如下
disp.format = mFbDev->format;
DisplayConfig config = DisplayConfig();
config.width = mFbDev->width;
config.height = mFbDev->height;
config.xdpi = mFbDev->xdpi;
config.ydpi = mFbDev->ydpi;
config.refresh = nsecs_t(1e9 / mFbDev->fps);
disp.configs.push_back(config);
disp.currentConfig = 0;
直接使用gralloc驱动中探测到的设备信息初始化primary屏幕信息
对于HWC_1.1+的设备,使用queryDisplayProperties去通过hwc驱动查询设备信息,这里初始化NUM_BUILTIN_DISPLAYS两个设备的信息
status_t HWComposer::queryDisplayProperties(int disp) {
LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
// use zero as default value for unspecified attributes
int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
memset(values, 0, sizeof(values));
const size_t MAX_NUM_CONFIGS = 128;
uint32_t configs[MAX_NUM_CONFIGS] = {0};
size_t numConfigs = MAX_NUM_CONFIGS;
status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
if (err != NO_ERROR) {
// this can happen if an unpluggable display is not connected
mDisplayData[disp].connected = false;
return err;
}
mDisplayData[disp].currentConfig = 0;
for (size_t c = 0; c < numConfigs; ++c) {
err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
DISPLAY_ATTRIBUTES, values);
// If this is a pre-1.5 HWC, it may not know about color transform, so
// try again with a smaller set of attributes
if (err != NO_ERROR) {
err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
PRE_HWC15_DISPLAY_ATTRIBUTES, values);
}
if (err != NO_ERROR) {
// we can't get this display's info. turn it off.
mDisplayData[disp].connected = false;
return err;
}
DisplayConfig config = DisplayConfig();
for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
switch (DISPLAY_ATTRIBUTES[i]) {
case HWC_DISPLAY_VSYNC_PERIOD:
config.refresh = nsecs_t(values[i]);
break;
case HWC_DISPLAY_WIDTH:
config.width = values[i];
break;
case HWC_DISPLAY_HEIGHT:
config.height = values[i];
break;
case HWC_DISPLAY_DPI_X:
config.xdpi = values[i] / 1000.0f;
break;
case HWC_DISPLAY_DPI_Y:
config.ydpi = values[i] / 1000.0f;
break;
case HWC_DISPLAY_COLOR_TRANSFORM:
config.colorMode = static_cast(values[i]);
break;
default:
ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
i, DISPLAY_ATTRIBUTES[i]);
break;
}
}
if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
float dpi = getDefaultDensity(config.width, config.height);
config.xdpi = dpi;
config.ydpi = dpi;
}
mDisplayData[disp].configs.push_back(config);
}
// FIXME: what should we set the format to?
mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
mDisplayData[disp].connected = true;
return NO_ERROR;
}
通过getDisplayConfigs查询设备支持的configure,这个函数也比较简单,查出多个configure,设置属性,并设置currentConfig=0
设置format = HAL_PIXEL_FORMAT_RGBA_8888 mDisplayData[disp].connected = true
其实这里如果没有插入其他设备的话只能读到第一个设备的属性信息,也就是只连接了一个设备
2 SurfaceFlinger::init() 创建DisplayDevice的过程
首先使用createBuiltinDisplayLocked函数创建两个内建设备的状态
void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
ALOGW_IF(mBuiltinDisplays[type],
"Overwriting display token for display type %d", type);
mBuiltinDisplays[type] = new BBinder();
// All non-virtual displays are currently considered secure.
DisplayDeviceState info(type, true);
mCurrentState.displays.add(mBuiltinDisplays[type], info);
}
为每个内建设备创建DisplayDevice数据结构 记录设备信息
wp token = mBuiltinDisplays[i];
sp producer;
sp consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
sp fbs = new FramebufferSurface(*mHwc, i,
consumer);
int32_t hwcId = allocateHwcDisplayId(type);
sp hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig());
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always
// assume a connected display is unblanked.
ALOGD("marking display %zu as acquired/unblanked", i);
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
mDisplays.add(token, hw);
这里边创建生产者消费者没有什么好说的,还创建了FramebuffersSurface 作为DisplayDevice的displaySurface
http://blog.csdn.net/ouo555/article/details/44340785
FramebuffersSurface与SurfaceFlingerConsumer一样都是用于包装消费者的,不同点在于SurfaceFlingerConsumer用于最终的图像合成.
最后如果是第一个设备则设置powerMode为NORMAL,放入devices队列
我们来看看设备构造的过程
DisplayDevice::DisplayDevice(
const sp& flinger,
DisplayType type,
int32_t hwcId,
#ifndef USE_HWC2
int format,
#endif
bool isSecure,
const wp& displayToken,
const sp& displaySurface,
const sp& producer,
EGLConfig config)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
mDisplaySurface(displaySurface),
mDisplay(EGL_NO_DISPLAY),
mSurface(EGL_NO_SURFACE),
mDisplayWidth(),
mDisplayHeight(),
#ifndef USE_HWC2
mFormat(),
#endif
mFlags(),
mPageFlipCount(),
mIsSecure(isSecure),
mLayerStack(NO_LAYER_STACK),
mOrientation(),
mPowerMode(HWC_POWER_MODE_OFF),
mActiveConfig(0)
{
Surface* surface;
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
/*
* Create our display's surface
*/
EGLSurface eglSurface;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
#ifdef USE_HWC2
config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
#else
config = RenderEngine::chooseEglConfig(display, format);
#endif
}
eglSurface = eglCreateWindowSurface(display, config, window, NULL);
eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough. We have to do this
// in two places:
// * Here, in case the display is composed entirely by HWC.
// * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
// window's swap interval in eglMakeCurrent, so they'll override the
// interval we set here.
if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
window->setSwapInterval(window, 0);
mConfig = config;
mDisplay = display;
mSurface = eglSurface;
#ifndef USE_HWC2
mFormat = format;
#endif
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
// virtual displays are always considered enabled
mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
switch (mType) {
case DISPLAY_PRIMARY:
mDisplayName = "Built-in Screen";
break;
case DISPLAY_EXTERNAL:
mDisplayName = "HDMI Screen";
break;
default:
mDisplayName = "Virtual Screen"; // e.g. Overlay #n
break;
}
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
surface->allocateBuffers();
#endif
}
之后设备就算初始化好了 执行SurfaceFlinger::onInitializeDisplays()
这个函数主要做了两件事情
1 setTransactionState更新事务状态 主要更新mCurrentState中的display状态和tranfactionFlags
2 setPowerModeInternal 设置powerMode为HWC_POWER_MODE_NORMAL
if (currentMode == HWC_POWER_MODE_OFF) {
// Turn on the display
getHwComposer().setPowerMode(type, mode);
if (type == DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
}
mVisibleRegionsDirty = true;
mHasPoweredOff = true;
repaintEverything();
struct sched_param param = {0};
param.sched_priority = 1;
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
ALOGW("Couldn't set SCHED_FIFO on display on");
}
} else if (mode == HWC_POWER_MODE_OFF) {
// Turn off the display
struct sched_param param = {0};
if (sched_setscheduler(0, SCHED_OTHER, ¶m) != 0) {
ALOGW("Couldn't set SCHED_OTHER on display off");
}
if (type == DisplayDevice::DISPLAY_PRIMARY) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenReleased();
}
getHwComposer().setPowerMode(type, mode);
mVisibleRegionsDirty = true;
// from this point on, SF will stop drawing on this display
} else {
getHwComposer().setPowerMode(type, mode);
}
这里包含三种状态的变换
1 从HWC_POWER_MODE_OFF状态到其他状态,也就是从灭屏幕不可见到可见,需要设置mVisibleRegionsDirty = true 重新绘制,mHasPoweredOff = true,这样绘制的时候就知道是从灭屏到亮屏幕第一次绘制时候使用
设置mRepaintEverything=1 ,表示重新绘制所有layer,设置调度优先级. 还要重新设置硬件发出vsync 校准vsync模型 开启vsync信号
2 由亮屏到灭屏幕 设置mVisibleRegionsDirty 关闭vsync
3 其他变化 直接设置设备的powermode
3 热插拔过程
先来分析热插过程
void HWComposer::hotplug(int disp, int connected) {
if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
disp, connected);
return;
}
queryDisplayProperties(disp);
// Do not teardown or recreate the primary display
if (disp != HWC_DISPLAY_PRIMARY) {
mEventHandler.onHotplugReceived(disp, bool(connected));
}
}
也是先判断虚拟设备不支持热插,然后查询设备属性,这个过程我们前面分析过,这个过程查询属性封装成mDisplayData保存在HWComposer的mDisplayData里面
然后调用mEventHandler.onHotplugReceived(disp, bool(connected)) 函数通知事件,这个接收者就是surfaceflinger
void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
if (mEventThread == NULL) {
// This is a temporary workaround for b/7145521. A non-null pointer
// does not mean EventThread has finished initializing, so this
// is not a correct fix.
ALOGW("WARNING: EventThread not started, ignoring hotplug");
return;
}
if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
Mutex::Autolock _l(mStateLock);
if (connected) {
createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
} else {
mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
mBuiltinDisplays[type].clear();
}
setTransactionFlags(eDisplayTransactionNeeded);
// Defer EventThread notification until SF has updated mDisplays.
}
}
1如果是连接设备使用createBuiltinDisplayLocked函数创建DisplayDeviceState函数放入mCurrentState,
注意这里并没有创建DisplayDevice设备信息,而是等待执行事务的时候创建设备,所以一会我们会看到添加事务的过程
2如果是设备移除的通知则删除DisplayDevice和DisplayDeviceState信息
最后根据display变化情况创建事务
setTransactionFlags(eDisplayTransactionNeeded)
这里设置了eDisplayTransactionNeeded的标志,并通知刷新设备信息,我们来看下eDisplayTransactionNeeded怎么处理,代码比较长 我们分段来看
代码在void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)函数里面
if (transactionFlags & eDisplayTransactionNeeded) {
// here we take advantage of Vector's copy-on-write semantics to
// improve performance by skipping the transaction entirely when
// know that the lists are identical
const KeyedVector< wp, DisplayDeviceState>& curr(mCurrentState.displays);
const KeyedVector< wp, DisplayDeviceState>& draw(mDrawingState.displays);
if (!curr.isIdenticalTo(draw)) {
我们要分析的代码就在满足了这个条件的代码块里面,这里面注释说利用vector的写时复制语义判断数组有没有改变,也就是isIdenticalTo函数,由于mDrawingState是之前的mCurrentState反转而来,所以
反转以后mCurrentState如果没有被写,isIdenticalTo返回true ,既然displaystate没有发生变化就没有必要做任何操作了. 我们这里由于添加了设备所以必然条件成立
// find the displays that were removed
// (ie: in drawing state but not in current state)
// also handle displays that changed
// (ie: displays that are in both lists)
for (size_t i=0 ; iconst ssize_t j = curr.indexOfKey(draw.keyAt(i));
if (j < 0) { //第一部分 c
// in drawing state but not in current state
if (!draw[i].isMainDisplay()) {
// Call makeCurrent() on the primary display so we can
// be sure that nothing associated with this display
// is current.
const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
sp hw(getDisplayDevice(draw.keyAt(i)));
if (hw != NULL)
hw->disconnect(getHwComposer());
if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
mEventThread->onHotplugReceived(draw[i].type, false);
mDisplays.removeItem(draw.keyAt(i));
} else {
ALOGW("trying to remove the main display");
}
} else {
// this display is in both lists. see if something changed. //第二部分
const DisplayDeviceState& state(curr[j]);
const wp& display(curr.keyAt(j));
const sp state_binder = IInterface::asBinder(state.surface);
const sp draw_binder = IInterface::asBinder(draw[i].surface);
if (state_binder != draw_binder) {
// changing the surface is like destroying and
// recreating the DisplayDevice, so we just remove it
// from the drawing state, so that it get re-added
// below.
sp hw(getDisplayDevice(display));
if (hw != NULL)
hw->disconnect(getHwComposer());
mDisplays.removeItem(display);
mDrawingState.displays.removeItemsAt(i);
dc--; i--;
// at this point we must loop to the next item
continue;
}
const sp disp(getDisplayDevice(display));
if (disp != NULL) {
if (state.layerStack != draw[i].layerStack) {
disp->setLayerStack(state.layerStack);
}
if ((state.orientation != draw[i].orientation)
|| (state.viewport != draw[i].viewport)
|| (state.frame != draw[i].frame))
{
disp->setProjection(state.orientation,
state.viewport, state.frame);
}
if (state.width != draw[i].width || state.height != draw[i].height) {
disp->setDisplaySize(state.width, state.height);
}
}
}
}
先看第一部分: in drawing state but not in current stat,说明该设备被移除了,如果不是main display ,才会处理,否则只会打印log.因为移除了就没的用了.
对于不是主显示设备的移除,首先调用主显示设备的makeCurrent方法,重新初始化elg上下文.然后disconnect要移除的设备,发送onHotplugReceived消息给关心该消息的人
第二部分this display is in both lists. see if something changed,连个队列都包含该设备,所以可能是有一些属性发生了变化
首先如果state_binder发生变化 说明设备已经重新创建,disconnect旧的,和移除displaydevice(因为一会要重建),如果设备没有重新创建,就要更新设备的一下属性:
layerStack,orientation,viewport,frame,width,height
// find displays that were added
// (ie: in current state but not in drawing state)
for (size_t i=0 ; iif (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
sp dispSurface;
sp producer;
sp bqProducer;
sp bqConsumer;
BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
new GraphicBufferAlloc());
int32_t hwcDisplayId = -1;
if (state.isVirtualDisplay()) {
// Virtual displays without a surface are dormant:
// they have external state (layer stack, projection,
// etc.) but no internal state (i.e. a DisplayDevice).
if (state.surface != NULL) {
int width = 0;
int status = state.surface->query(
NATIVE_WINDOW_WIDTH, &width);
ALOGE_IF(status != NO_ERROR,
"Unable to query width (%d)", status);
int height = 0;
status = state.surface->query(
NATIVE_WINDOW_HEIGHT, &height);
ALOGE_IF(status != NO_ERROR,
"Unable to query height (%d)", status);
if (mUseHwcVirtualDisplays &&
(MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
(width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
height <= MAX_VIRTUAL_DISPLAY_DIMENSION))) {
hwcDisplayId = allocateHwcDisplayId(state.type);
}
sp vds = new VirtualDisplaySurface(
*mHwc, hwcDisplayId, state.surface,
bqProducer, bqConsumer, state.displayName);
dispSurface = vds;
producer = vds;
}
} else {
ALOGE_IF(state.surface!=NULL,
"adding a supported display, but rendering "
"surface is provided (%p), ignoring it",
state.surface.get());
hwcDisplayId = allocateHwcDisplayId(state.type);
// for supported (by hwc) displays we provide our
// own rendering surface
dispSurface = new FramebufferSurface(*mHwc, state.type,
bqConsumer);
producer = bqProducer;
}
const wp& display(curr.keyAt(i));
if (dispSurface != NULL) {
sp hw = new DisplayDevice(this,
state.type, hwcDisplayId,
mHwc->getFormat(hwcDisplayId), state.isSecure,
display, dispSurface, producer,
mRenderEngine->getEGLConfig());
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
hw->setDisplayName(state.displayName);
mDisplays.add(display, hw);
if (state.isVirtualDisplay()) {
if (hwcDisplayId >= 0) {
mHwc->setVirtualDisplayProperties(hwcDisplayId,
hw->getWidth(), hw->getHeight(),
hw->getFormat());
}
} else {
mEventThread->onHotplugReceived(state.type, true);
}
}
}
}
这里面就是处理新增的设备,还有前面recreate的设备,因为已经从drawState的displays中移除,这里也被认为是新的设备
首先第一步就是为设备创建生产者消费者,然后用surface包装生产者,对于虚拟设备使用VirtualDisplaySurface包装生产者,
物理设备则使用FramebufferSurface包装.
第二部分则是创建DisplayDevice节点
对多个display管理最终要的地方还是绘制的地方.下面就来分析下虚拟设备还真是设备是如何进行绘制的
绘制的过程主要在Surface::handleMessageRefresh()函数中,有几个关键函数
void SurfaceFlinger::rebuildLayerStacks() {
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_CALL();
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
const LayerVector& layers(mDrawingState.layersSortedByZ);
for (size_t dpy=0 ; dpy > layersSortedByZ;
const sp& hw(mDisplays[dpy]);
const Transform& tr(hw->getTransform());
const Rect bounds(hw->getBounds());
if (hw->isDisplayOn()) {
SurfaceFlinger::computeVisibleRegions(layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);
const size_t count = layers.size();
for (size_t i=0 ; i& layer(layers[i]);
const Layer::State& s(layer->getDrawingState());
if (s.layerStack == hw->getLayerStack()) {
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
if (!drawRegion.isEmpty()) {
layersSortedByZ.add(layer);
}
}
}
}
hw->setVisibleLayersSortedByZ(layersSortedByZ);
hw->undefinedRegion.set(bounds);
hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
hw->dirtyRegion.orSelf(dirtyRegion);
}
}
这个函数会对每个Display上的layer进行计算,那么如何区分layer是在哪个Display呢?
如果DisplayDevice->layerStack == Layer->layerStack 怎证这个layer在这个Display上,
这个函数主要计算出每个layer的三个区域,后面分析区域计算的文章中会详细分析这方面的内容,读者只要
知道这里计算每个layer的显示区域就可以了
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
layer->setVisibleNonTransparentRegion(
visibleRegion.subtract(transparentRegion));
计算完成每个layer的区域就可以把包含要重新绘制的layer按照z轴的顺序放到DisplayDevice里面了
hw->setVisibleLayersSortedByZ(layersSortedByZ);
第二个比较重要的函数
void SurfaceFlinger::setUpHWComposer() {
//第一段
for (size_t dpy=0 ; dpy.size() ; dpy++) {
bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
// If nothing has changed (!dirty), don't recompose.
// If something changed, but we don't currently have any visible layers,
// and didn't when we last did a composition, then skip it this time.
// The second rule does two things:
// - When all layers are removed from a display, we'll emit one black
// frame, then nothing more until we get new layers.
// - When a display is created with a private layer stack, we won't
// emit any black frames until a layer is added to the layer stack.
bool mustRecompose = dirty && !(empty && wasEmpty);
ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
"dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
mustRecompose ? "doing" : "skipping",
dirty ? "+" : "-",
empty ? "+" : "-",
wasEmpty ? "+" : "-");
mDisplays[dpy]->beginFrame(mustRecompose);
if (mustRecompose) {
mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
}
}
//第二段
HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
// build the h/w work list
if (CC_UNLIKELY(mHwWorkListDirty)) {
mHwWorkListDirty = false;
for (size_t dpy=0 ; dpy.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
if (hwc.createWorkList(id, count) == NO_ERROR) {
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && iconst sp& layer(currentLayers[i]);
layer->setGeometry(hw, *cur);
if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
cur->setSkip(true);
}
}
}
}
}
}
//第三段
// set the per-frame data
for (size_t dpy=0 ; dpy.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i/*
* update the per-frame h/w composer data for each layer
* and build the transparent region of the FB
*/
const sp& layer(currentLayers[i]);
layer->setPerFrameData(hw, *cur);
}
}
}
//第四段
// If possible, attempt to use the cursor overlay on each display.
for (size_t dpy=0 ; dpy.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && iconst sp& layer(currentLayers[i]);
if (layer->isPotentialCursor()) {
cur->setIsCursorLayerHint();
break;
}
}
}
}
//第五段
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
//第六段
for (size_t dpy=0 ; dpy.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
hw->prepareFrame(hwc);
}
}
}
上面的函数可以分成6段阅读
第一段主要就是调用mDisplays[dpy]->beginFrame(mustRecompose);函数
status_t DisplayDevice::beginFrame(bool mustRecompose) const {
return mDisplaySurface->beginFrame(mustRecompose);
}
对于物理设备和虚拟设备DisplaySurface是不一样的,我们先看物理设备,DisplaySurface使用的是FramebufferSurface类创建
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
return NO_ERROR;
}
什么都没做,再看下虚拟设备
status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
if (mDisplayId < 0)
return NO_ERROR;
mMustRecompose = mustRecompose;
VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
"Unexpected beginFrame() in %s state", dbgStateStr());
mDbgState = DBG_STATE_BEGUN;
return refreshOutputBuffer();
}
status_t VirtualDisplaySurface::refreshOutputBuffer() {
if (mOutputProducerSlot >= 0) {
mSource[SOURCE_SINK]->cancelBuffer(
mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot),
mOutputFence);
}
int sslot;
status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
&sslot, &mOutputFence);
if (result < 0)
return result;
mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
// On GLES-only frames, we don't have the right output buffer acquire fence
// until after GLES calls queueBuffer(). So here we just set the buffer
// (for use in HWC prepare) but not the fence; we'll call this again with
// the proper fence once we have it.
result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE,
mProducerBuffers[mOutputProducerSlot]);
return result;
}
int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
if (source == SOURCE_SCRATCH) {
return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
} else {
return sslot;
}
}
status_t HWComposer::setOutputBuffer(int32_t id, const sp& acquireFence,
const sp& buf) {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return BAD_INDEX;
if (id < VIRTUAL_DISPLAY_ID_BASE)
return INVALID_OPERATION;
DisplayData& disp(mDisplayData[id]);
disp.outbufHandle = buf->handle;
disp.outbufAcquireFence = acquireFence;
return NO_ERROR;
}
对于虚拟设备,生产者的服务端不在Surfaceflinger中,而是在另一端要获取数据的应用程序中,如screenrecoder,所以在VirtualDisplaySurface中会有两个生产者,下面以screenrecoder为例方便说明,mSource[SOURCE_SINK]用于存放screenrecoder中的生产者的BpBinder端,而mSource[SOURCE_SCRATCH]则便是surfaceflinger这端的生产者.
所以在refreshOutputBuffer函数中会重新从screenrecoder中dequeue一块buffer. 然后调用mapSource2ProducerSlot函数其实啥都没做,把新获取到的buffer坐标保存在mOutputProducerSlot中.最后调用mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE,
mProducerBuffers[mOutputProducerSlot])设置outBuffer,用于输出合成结果.
第二,三,四段填充worklist数据
第五段 询问hwc设备该如何合成
第六段
VirtualDisplaySurface | FramebufferSurface
第六阶段只是针对虚拟设备准备的,在VirtualDisplaySurface里面实现,会根据合成的方式重新申请buffer,
这里重新申请buffer的原因是因为mOutputFormat产生了变化 目的就是更好的使用hwc 的rgb转yuv功能
之后下一步做的就是doComposition 函数
void SurfaceFlinger::doComposition() {
ATRACE_CALL();
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
for (size_t dpy=0 ; dpy//阶段1
const sp& hw(mDisplays[dpy]);
if (hw->isDisplayOn()) {
// transform the dirty region into this screen's coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
// repaint the framebuffer (if needed)
doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear();
hw->flip(hw->swapRegion);
hw->swapRegion.clear();
}
// inform the h/w that we're done compositing
hw->compositionComplete();
}
postFramebuffer();
}
这里比较重要的步骤是doDisplayComposition,里面会调用每个设备的hw->swapBuffers(getHwComposer()); 方法
所以最终会进行queueBuffer,最终实行到设备的Surface的onFrameAvailable函数,如果单纯使用gpu选咱的话,就会提交数据
到framebuffer,否则的话还要经过合成
int HWComposer::fbPost(int32_t id,
const sp& acquireFence, const sp& buffer) { //需要进行硬件合成
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
return setFramebufferTarget(id, acquireFence, buffer);
} else { //直接提交到framebuffer
acquireFence->waitForever("HWComposer::fbPost");
return mFbDev->post(mFbDev, buffer->handle);
}
}
对于虚拟设备,swapbuffer的过程还有重要的一步
status_t VirtualDisplaySurface::advanceFrame() 直接进行硬件合成
postFramebuffer()则是最终要的一步 提交数据,这之后就算真正完成了数据提交
最后再解释下虚拟设备的原理,虚拟设备的生产者在客户端一端,会把数据写道生产者,
可以参考 frameworks/av/cmds/screenrecord代码