Android(安卓)surfaceflinger(3)-DisplayDevice封装
16lz
2021-12-04
上一篇文章介绍了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(this)); // initialize our non-virtual displays for (size_t i=0 ; iif (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) { // All non-virtual displays are currently considered secure. bool isSecure = true; createBuiltinDisplayLocked(type);//见第2节 wp token = mBuiltinDisplays[i]; sp producer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, new GraphicBufferAlloc());//见第3节 sp fbs = new FramebufferSurface(*mHwc, i,consumer);//见第4节 int32_t hwcId = allocateHwcDisplayId(type); sp 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& flinger, DisplayType type, int32_t hwcId, int format, 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(), 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进行交互的。未完待续……
更多相关文章
- 1.3 Android(安卓)App 组件架构
- 安装好android的adt以后重启eclipse,但是没有创建AVD的图标
- android Notification 的使用
- Android(安卓)内存数据库
- Android(安卓)创建自定义View 实现TopBar
- [android] android下创建一个sqlite数据库
- Android(安卓)Studio 首次创建工程下载Gradle失败
- Android(安卓)cocos2d-x开发(三)之创建Android工程和编译
- Android(安卓)Fragment viewPage TabLayout用法。