上一篇文章介绍了HWComposer的创建及初始化,本文将根据上述创建的HWComposer封装出DisplayDevice对象进行分析。
1、引言
在此之前已经分析了HWComposer,接下来继续分析SurfaceFlinger::init的后续操作
void SurfaceFlinger::init() {
//详见http://blog.csdn.net/marshal_zsx/article/details/78054285
mHwc = new HWComposer(this,*static_cast<HWComposer::EventHandler *>(this));
// initialize our non-virtual displays
for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
// All non-virtual displays are currently considered secure.
bool isSecure = true;
createBuiltinDisplayLocked(type);//见第2节
wp<IBinder> token = mBuiltinDisplays[i];
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());//见第3节
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,consumer);//见第4节
int32_t hwcId = allocateHwcDisplayId(type);
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,mRenderEngine->getEGLConfig());//见第5节
mDisplays.add(token, hw);
}
}
// start boot animation
startBootAnim();//见下一篇文章
}
2、token创建
Android6.0支持多屏显示,为了区分不同的屏幕,需要创建不同的token(即使每一块屏幕唯一对应一个IBinder);并用mBuiltinDisplays数组进行管理,具体代码如下:
void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
ALOGW_IF(mBuiltinDisplays[type],
"Overwriting display token for display type %d", type);
mBuiltinDisplays[type] = new BBinder();
DisplayDeviceState info(type);
// All non-virtual displays are currently considered secure.
info.isSecure = true;
mCurrentState.displays.add(mBuiltinDisplays[type], info);
}
3、建立bufferqueue生产者消费者
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
const sp<IGraphicBufferAlloc>& allocator) {
LOG_ALWAYS_FATAL_IF(outProducer == NULL,
"BufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
"BufferQueue: outConsumer must not be NULL");
sp<BufferQueueCore> core(new BufferQueueCore(allocator));
LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore");
//创建生产者
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
LOG_ALWAYS_FATAL_IF(producer == NULL,
"BufferQueue: failed to create BufferQueueProducer");
//创建消费者
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
LOG_ALWAYS_FATAL_IF(consumer == NULL,
"BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
4、创建FramebufferSurface
FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
const sp<IGraphicBufferConsumer>& consumer) :
ConsumerBase(consumer),
mDisplayType(disp),
mCurrentBufferSlot(-1),
mCurrentBuffer(0),
mHwc(hwc)
{
mName = "FramebufferSurface";
mConsumer->setConsumerName(mName);
int usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER;
if(disp != 0) {
usage |= GRALLOC_USAGE_HW_FBX;
}
//mConsumer是父类ConsumerBase的成员变量,故以下是调用IGraphicBufferConsumer对应的方法
mConsumer->setConsumerUsageBits(usage);
mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));//设置buffer格式
mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));//设置buffer大小
mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}
5、创建DisplayDevice
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
int32_t hwcId,
int format,
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& 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(), mFormat(),
mFlags(),
mPageFlipCount(),
mIsSecure(isSecure),
mSecureLayerVisible(false),
mLayerStack(NO_LAYER_STACK),
mOrientation(),
mPowerMode(HWC_POWER_MODE_OFF),
mActiveConfig(0)
{
mNativeWindow = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
/*
* Create our display's surface
*/
EGLSurface surface;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
config = RenderEngine::chooseEglConfig(display, format);
}
surface = eglCreateWindowSurface(display, config, window, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
mConfig = config;
mDisplay = display;
mSurface = surface;
mFormat = format;
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;
}
//初始化显示方向转换。
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
创建DisplayDevice对象完成后,调用mDisplays.add(token, hw)加入到mDisplays键值容器中,这就形成了每个屏幕都有唯一指定的token。
6、总结与展望
当surfaceflinger初始化完成后,就会去启动开机动画;后面将分析开机动画是如何与surfaceflinger进行交互的。未完待续……