显示HWC合成(hwc_display_contents_1_t,hwc_layer_1_t数据结构关系)

本文深入剖析了HWC中的关键数据结构hwc_display_contents_1_t和hwc_layer_1_t,展示了这些结构如何用于组织和管理显示设备上的图层。同时,文章详细解释了这些数据结构在SurfaceFlinger与HWC模块交互过程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自: http://blog.youkuaiyun.com/kc58236582/article/details/70146317

在之前的博客中,分析了SurfaceFlinger的流程,以及hwc和Gralloc模块的大致功能,但是对其中一些数据结构不是很清楚. 这篇博客我们主要从创建hwc_display_contents_1_t数据结构入手开始对hal层 hwc的一些数据结构进行分析。

创建hwc_display_contents_1_t

我们先来看看setUpHWComposer函数中如下代码,会遍历各个display(每个显示设备),然后调用HWComposer的createWorkList函数,并且把当前layer的数量count作为参数。后面还会调用hwc的prepare函数。

[cpp]  view plain  copy
  1. ......  
  2. HWComposer& hwc(getHwComposer());  
  3. if (hwc.initCheck() == NO_ERROR) {  
  4.     // build the h/w work list  
  5.     if (CC_UNLIKELY(mHwWorkListDirty)) {  
  6.         mHwWorkListDirty = false;  
  7.         for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {  
  8.             sp<const DisplayDevice> hw(mDisplays[dpy]);  
  9.             const int32_t id = hw->getHwcDisplayId();  
  10.             if (id >= 0) {  
  11.                 const Vector< sp<Layer> >& currentLayers(  
  12.                     hw->getVisibleLayersSortedByZ());  
  13.                 const size_t count = currentLayers.size();  
  14.                 if (hwc.createWorkList(id, count) == NO_ERROR) {  
  15.                     ......  
  16.                 }  
  17.             }  
  18.         }  
  19.     }  
  20. ......  
  21. status_t err = hwc.prepare();  
  22. ......  

我们先来看DisplayData数据结构,它就代表一个显示设备的数据。其中list变量(hwc_display_contents_1_t类型)包括这个显示设备上所有的layer数据,layer数据放在hwLayers中。这个list的最后一个就是framebufferTarget(gpu合成之后的layer),然后在DisplayData数据结构中单独给了一个变量framebufferTarget。

[cpp]  view plain  copy
  1. struct DisplayData {  
  2.     DisplayData();  
  3.     ~DisplayData();  
  4.     Vector<DisplayConfig> configs;  
  5.     size_t currentConfig;  
  6.     uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1  
  7.     bool connected;  
  8.     bool hasFbComp;  
  9.     bool hasOvComp;  
  10.     size_t capacity;  
  11.     hwc_display_contents_1* list;//各个layer  
  12.     hwc_layer_1* framebufferTarget;//gpu合成之后的layer  
  13.     buffer_handle_t fbTargetHandle;  
  14.     sp<Fence> lastRetireFence;  // signals when the last set op retires  
  15.     sp<Fence> lastDisplayFence; // signals when the last set op takes  
  16.                                 // effect on screen  
  17.     buffer_handle_t outbufHandle;  
  18.     sp<Fence> outbufAcquireFence;  
  19.   
  20.     // protected by mEventControlLock  
  21.     int32_t events;  
  22. };  

createWorkList函数先是计算我们要申请layer的内存大小,然后通过malloc申请内存,并且地址赋给disp.list.后面我们把disp.list->hwLayers的最后一个其实就是gpu合成之后的layer framebufferTarget。当然我们也就把这个hwc_layer_1赋给了disp.framebufferTarget.

[cpp]  view plain  copy
  1. status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {  
  2.     if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {  
  3.         return BAD_INDEX;  
  4.     }  
  5.   
  6.     if (mHwc) {  
  7.         DisplayData& disp(mDisplayData[id]);  
  8.         if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  9.             // we need space for the HWC_FRAMEBUFFER_TARGET  
  10.             numLayers++;  
  11.         }  
  12.         if (disp.capacity < numLayers || disp.list == NULL) {  
  13.             size_t size = sizeof(hwc_display_contents_1_t)  
  14.                     + numLayers * sizeof(hwc_layer_1_t);//申请内存的大小  
  15.             free(disp.list);  
  16.             disp.list = (hwc_display_contents_1_t*)malloc(size);//malloc内存  
  17.             disp.capacity = numLayers;  
  18.         }  
  19.         if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  20.             disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];//list的hwLayers最后一个就是framebufferTarget  
  21.             memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));  
  22.             const DisplayConfig& currentConfig =  
  23.                     disp.configs[disp.currentConfig];  
  24.             const hwc_rect_t r = { 0, 0,  
  25.                     (int) currentConfig.width, (int) currentConfig.height };  
  26.             disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;//类型变成target的  
  27.             disp.framebufferTarget->hints = 0;  
  28.             disp.framebufferTarget->flags = 0;  
  29.             disp.framebufferTarget->handle = disp.fbTargetHandle;  
  30.             disp.framebufferTarget->transform = 0;  
  31.             disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;  
  32.             if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {  
  33.                 disp.framebufferTarget->sourceCropf.left = 0;  
  34.                 disp.framebufferTarget->sourceCropf.top = 0;  
  35.                 disp.framebufferTarget->sourceCropf.right =  
  36.                         currentConfig.width;  
  37.                 disp.framebufferTarget->sourceCropf.bottom =  
  38.                         currentConfig.height;  
  39.             } else {  
  40.                 disp.framebufferTarget->sourceCrop = r;  
  41.             }  
  42.             disp.framebufferTarget->displayFrame = r;  
  43.             disp.framebufferTarget->visibleRegionScreen.numRects = 1;  
  44.             disp.framebufferTarget->visibleRegionScreen.rects =  
  45.                 &disp.framebufferTarget->displayFrame;  
  46.             disp.framebufferTarget->acquireFenceFd = -1;  
  47.             disp.framebufferTarget->releaseFenceFd = -1;  
  48.             disp.framebufferTarget->planeAlpha = 0xFF;  
  49.         }  
  50.         disp.list->retireFenceFd = -1;  
  51.         disp.list->flags = HWC_GEOMETRY_CHANGED;  
  52.         disp.list->numHwLayers = numLayers;  
  53.     }  
  54.     return NO_ERROR;  
  55. }  
hwc_display_contents_1的数据结构如下,代表的是一个设备的数据。

[cpp]  view plain  copy
  1. typedef struct hwc_display_contents_1 {  
  2.     /* File descriptor referring to a Sync HAL fence object which will signal 
  3.      * when this composition is retired. For a physical display, a composition 
  4.      * is retired when it has been replaced on-screen by a subsequent set. For 
  5.      * a virtual display, the composition is retired when the writes to 
  6.      * outputBuffer are complete and can be read. The fence object is created 
  7.      * and returned by the set call; this field will be -1 on entry to prepare 
  8.      * and set. SurfaceFlinger will close the returned file descriptor. 
  9.      */  
  10.     int retireFenceFd;  
  11.   
  12.     union {  
  13.         /* Fields only relevant for HWC_DEVICE_VERSION_1_0. */  
  14.         struct {  
  15.             /* (dpy, sur) is the target of SurfaceFlinger's OpenGL ES 
  16.              * composition for HWC_DEVICE_VERSION_1_0. They aren't relevant to 
  17.              * prepare. The set call should commit this surface atomically to 
  18.              * the display along with any overlay layers. 
  19.              */  
  20.             hwc_display_t dpy;  
  21.             hwc_surface_t sur;  
  22.         };  
  23.   
  24.         /* These fields are used for virtual displays when the h/w composer 
  25.          * version is at least HWC_DEVICE_VERSION_1_3. */  
  26.         struct {  
  27.             /* outbuf is the buffer that receives the composed image for 
  28.              * virtual displays. Writes to the outbuf must wait until 
  29.              * outbufAcquireFenceFd signals. A fence that will signal when 
  30.              * writes to outbuf are complete should be returned in 
  31.              * retireFenceFd. 
  32.              * 
  33.              * This field is set before prepare(), so properties of the buffer 
  34.              * can be used to decide which layers can be handled by h/w 
  35.              * composer. 
  36.              * 
  37.              * If prepare() sets all layers to FRAMEBUFFER, then GLES 
  38.              * composition will happen directly to the output buffer. In this 
  39.              * case, both outbuf and the FRAMEBUFFER_TARGET layer's buffer will 
  40.              * be the same, and set() has no work to do besides managing fences. 
  41.              * 
  42.              * If the TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS board config 
  43.              * variable is defined (not the default), then this behavior is 
  44.              * changed: if all layers are marked for FRAMEBUFFER, GLES 
  45.              * composition will take place to a scratch framebuffer, and 
  46.              * h/w composer must copy it to the output buffer. This allows the 
  47.              * h/w composer to do format conversion if there are cases where 
  48.              * that is more desirable than doing it in the GLES driver or at the 
  49.              * virtual display consumer. 
  50.              * 
  51.              * If some or all layers are marked OVERLAY, then the framebuffer 
  52.              * and output buffer will be different. As with physical displays, 
  53.              * the framebuffer handle will not change between frames if all 
  54.              * layers are marked for OVERLAY. 
  55.              */  
  56.             buffer_handle_t outbuf;  
  57.   
  58.             /* File descriptor for a fence that will signal when outbuf is 
  59.              * ready to be written. The h/w composer is responsible for closing 
  60.              * this when no longer needed. 
  61.              * 
  62.              * Will be -1 whenever outbuf is NULL, or when the outbuf can be 
  63.              * written immediately. 
  64.              */  
  65.             int outbufAcquireFenceFd;  
  66.         };  
  67.     };  
  68.   
  69.     /* List of layers that will be composed on the display. The buffer handles 
  70.      * in the list will be unique. If numHwLayers is 0, all composition will be 
  71.      * performed by SurfaceFlinger. 
  72.      */  
  73.     uint32_t flags;  
  74.     size_t numHwLayers;//layer的个数  
  75.     hwc_layer_1_t hwLayers[0];//各个layer的起始指针  
  76.   
  77. } hwc_display_contents_1_t;  

再来看看hwc_layer_1 的数据结构

[cpp]  view plain  copy
  1. typedef struct hwc_layer_1 {  
  2.     /* 
  3.      * compositionType is used to specify this layer's type and is set by either 
  4.      * the hardware composer implementation, or by the caller (see below). 
  5.      * 
  6.      *  This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER 
  7.      *  before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is 
  8.      *  also set, otherwise, this field is preserved between (*prepare)() 
  9.      *  calls. 
  10.      * 
  11.      * HWC_BACKGROUND 
  12.      *   Always set by the caller before calling (*prepare)(), this value 
  13.      *   indicates this is a special "background" layer. The only valid field 
  14.      *   is backgroundColor. 
  15.      *   The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT 
  16.      *   handle the background color. 
  17.      * 
  18.      * 
  19.      * HWC_FRAMEBUFFER_TARGET 
  20.      *   Always set by the caller before calling (*prepare)(), this value 
  21.      *   indicates this layer is the framebuffer surface used as the target of 
  22.      *   OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY 
  23.      *   or HWC_BACKGROUND, then no OpenGL ES composition will be done, and 
  24.      *   this layer should be ignored during set(). 
  25.      * 
  26.      *   This flag (and the framebuffer surface layer) will only be used if the 
  27.      *   HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions, 
  28.      *   the OpenGL ES target surface is communicated by the (dpy, sur) fields 
  29.      *   in hwc_compositor_device_1_t. 
  30.      * 
  31.      *   This value cannot be set by the HWC implementation. 
  32.      * 
  33.      * 
  34.      * HWC_FRAMEBUFFER 
  35.      *   Set by the caller before calling (*prepare)() ONLY when the 
  36.      *   HWC_GEOMETRY_CHANGED flag is also set. 
  37.      * 
  38.      *   Set by the HWC implementation during (*prepare)(), this indicates 
  39.      *   that the layer will be drawn into the framebuffer using OpenGL ES. 
  40.      *   The HWC can toggle this value to HWC_OVERLAY to indicate it will 
  41.      *   handle the layer. 
  42.      * 
  43.      * 
  44.      * HWC_OVERLAY 
  45.      *   Set by the HWC implementation during (*prepare)(), this indicates 
  46.      *   that the layer will be handled by the HWC (ie: it must not be 
  47.      *   composited with OpenGL ES). 
  48.      * 
  49.      * 
  50.      * HWC_SIDEBAND 
  51.      *   Set by the caller before calling (*prepare)(), this value indicates 
  52.      *   the contents of this layer come from a sideband video stream. 
  53.      * 
  54.      *   The h/w composer is responsible for receiving new image buffers from 
  55.      *   the stream at the appropriate time (e.g. synchronized to a separate 
  56.      *   audio stream), compositing them with the current contents of other 
  57.      *   layers, and displaying the resulting image. This happens 
  58.      *   independently of the normal prepare/set cycle. The prepare/set calls 
  59.      *   only happen when other layers change, or when properties of the 
  60.      *   sideband layer such as position or size change. 
  61.      * 
  62.      *   If the h/w composer can't handle the layer as a sideband stream for 
  63.      *   some reason (e.g. unsupported scaling/blending/rotation, or too many 
  64.      *   sideband layers) it can set compositionType to HWC_FRAMEBUFFER in 
  65.      *   (*prepare)(). However, doing so will result in the layer being shown 
  66.      *   as a solid color since the platform is not currently able to composite 
  67.      *   sideband layers with the GPU. This may be improved in future 
  68.      *   versions of the platform. 
  69.      * 
  70.      * 
  71.      * HWC_CURSOR_OVERLAY 
  72.      *   Set by the HWC implementation during (*prepare)(), this value 
  73.      *   indicates the layer's composition will now be handled by the HWC. 
  74.      *   Additionally, the client can now asynchronously update the on-screen 
  75.      *   position of this layer using the setCursorPositionAsync() api. 
  76.      */  
  77.     int32_t compositionType;//注意上面注释  
  78.   
  79.     /* 
  80.      * hints is bit mask set by the HWC implementation during (*prepare)(). 
  81.      * It is preserved between (*prepare)() calls, unless the 
  82.      * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0. 
  83.      * 
  84.      * see hwc_layer_t::hints 
  85.      */  
  86.     uint32_t hints;  
  87.   
  88.     /* see hwc_layer_t::flags */  
  89.     uint32_t flags;  
  90.   
  91.     union {  
  92.         /* color of the background.  hwc_color_t.a is ignored */  
  93.         hwc_color_t backgroundColor;  
  94.   
  95.         struct {  
  96.             union {  
  97.                 /* When compositionType is HWC_FRAMEBUFFER, HWC_OVERLAY, 
  98.                  * HWC_FRAMEBUFFER_TARGET, this is the handle of the buffer to 
  99.                  * compose. This handle is guaranteed to have been allocated 
  100.                  * from gralloc using the GRALLOC_USAGE_HW_COMPOSER usage flag. 
  101.                  * If the layer's handle is unchanged across two consecutive 
  102.                  * prepare calls and the HWC_GEOMETRY_CHANGED flag is not set 
  103.                  * for the second call then the HWComposer implementation may 
  104.                  * assume that the contents of the buffer have not changed. */  
  105.                 buffer_handle_t handle;//放数据的变量,下篇博客分析  
  106.   
  107.                 /* When compositionType is HWC_SIDEBAND, this is the handle 
  108.                  * of the sideband video stream to compose. */  
  109.                 const native_handle_t* sidebandStream;  
  110.             };  
  111.   
  112.             /* transformation to apply to the buffer during composition */  
  113.             uint32_t transform;  
  114.   
  115.             /* blending to apply during composition */  
  116.             int32_t blending;  
  117.   
  118.             ......  
  119.   
  120.             /* where to composite the sourceCrop onto the display. The sourceCrop 
  121.              * is scaled using linear filtering to the displayFrame. The origin is the 
  122.              * top-left corner of the screen. 
  123.              */  
  124.             hwc_rect_t displayFrame;  
  125.   
  126.             /* visible region in screen space. The origin is the 
  127.              * top-left corner of the screen. 
  128.              * The visible region INCLUDES areas overlapped by a translucent layer. 
  129.              */  
  130.             hwc_region_t visibleRegionScreen;  
  131.   
  132.             /* Sync fence object that will be signaled when the buffer's 
  133.              * contents are available. May be -1 if the contents are already 
  134.              * available. This field is only valid during set(), and should be 
  135.              * ignored during prepare(). The set() call must not wait for the 
  136.              * fence to be signaled before returning, but the HWC must wait for 
  137.              * all buffers to be signaled before reading from them. 
  138.              * 
  139.              * HWC_FRAMEBUFFER layers will never have an acquire fence, since 
  140.              * reads from them are complete before the framebuffer is ready for 
  141.              * display. 
  142.              * 
  143.              * HWC_SIDEBAND layers will never have an acquire fence, since 
  144.              * synchronization is handled through implementation-defined 
  145.              * sideband mechanisms. 
  146.              * 
  147.              * The HWC takes ownership of the acquireFenceFd and is responsible 
  148.              * for closing it when no longer needed. 
  149.              */  
  150.             int acquireFenceFd;  
  151.   
  152.             /* During set() the HWC must set this field to a file descriptor for 
  153.              * a sync fence object that will signal after the HWC has finished 
  154.              * reading from the buffer. The field is ignored by prepare(). Each 
  155.              * layer should have a unique file descriptor, even if more than one 
  156.              * refer to the same underlying fence object; this allows each to be 
  157.              * closed independently. 
  158.              * 
  159.              * If buffer reads can complete at significantly different times, 
  160.              * then using independent fences is preferred. For example, if the 
  161.              * HWC handles some layers with a blit engine and others with 
  162.              * overlays, then the blit layers can be reused immediately after 
  163.              * the blit completes, but the overlay layers can't be reused until 
  164.              * a subsequent frame has been displayed. 
  165.              * 
  166.              * Since HWC doesn't read from HWC_FRAMEBUFFER layers, it shouldn't 
  167.              * produce a release fence for them. The releaseFenceFd will be -1 
  168.              * for these layers when set() is called. 
  169.              * 
  170.              * Since HWC_SIDEBAND buffers don't pass through the HWC client, 
  171.              * the HWC shouldn't produce a release fence for them. The 
  172.              * releaseFenceFd will be -1 for these layers when set() is called. 
  173.              * 
  174.              * The HWC client taks ownership of the releaseFenceFd and is 
  175.              * responsible for closing it when no longer needed. 
  176.              */  
  177.             int releaseFenceFd;  
  178.   
  179.             ......  
  180.   
  181.             /* 
  182.              * Availability: HWC_DEVICE_API_VERSION_1_5 
  183.              * 
  184.              * This defines the region of the source buffer that has been 
  185.              * modified since the last frame. 
  186.              * 
  187.              * If surfaceDamage.numRects > 0, then it may be assumed that any 
  188.              * portion of the source buffer not covered by one of the rects has 
  189.              * not been modified this frame. If surfaceDamage.numRects == 0, 
  190.              * then the whole source buffer must be treated as if it had been 
  191.              * modified. 
  192.              * 
  193.              * If the layer's contents are not modified relative to the prior 
  194.              * prepare/set cycle, surfaceDamage will contain exactly one empty 
  195.              * rect ([0, 0, 0, 0]). 
  196.              * 
  197.              * The damage rects are relative to the pre-transformed buffer, and 
  198.              * their origin is the top-left corner. 
  199.              */  
  200.             hwc_region_t surfaceDamage;  
  201.         };  
  202.     };  
  203.   
  204. ......  
  205.   
  206. } hwc_layer_1_t;  

我们再来看HWComposer的prepare函数,这个函数主要是调用了HWC模块的prepare函数,然后根据disp.list中各个layer数据再修改disp中相应的变量,比如hasOvComp是否有需要hwc合成,hasFbComp是否需要gpu合成。而HWComposer的prepare函数主要就是将对应的图层的类型设置为HWC_FRAMEBUFFER代表就是需要GPU合成的意思。

还有就是HWComposer中的mList就是对应各个显示设备,是DisplayData的list变量就是hwc_display_contents_1

[cpp]  view plain  copy
  1. status_t HWComposer::prepare() {  
  2.     Mutex::Autolock _l(mDisplayLock);  
  3.     for (size_t i=0 ; i<mNumDisplays ; i++) {  
  4.         DisplayData& disp(mDisplayData[i]);  
  5.         if (disp.framebufferTarget) {  
  6.             // make sure to reset the type to HWC_FRAMEBUFFER_TARGET  
  7.             // DO NOT reset the handle field to NULL, because it's possible  
  8.             // that we have nothing to redraw (eg: eglSwapBuffers() not called)  
  9.             // in which case, we should continue to use the same buffer.  
  10.             LOG_FATAL_IF(disp.list == NULL);  
  11.             disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;//将framebufferTarget的类型赋值  
  12.         }  
  13.         if (!disp.connected && disp.list != NULL) {  
  14.             ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",  
  15.                   i, disp.list->numHwLayers);  
  16.         }  
  17.         mLists[i] = disp.list;//mLists中的数据就是对应各个显示设备的hwc_display_contents_1  
  18.         if (mLists[i]) {  
  19.             if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {  
  20.                 mLists[i]->outbuf = disp.outbufHandle;  
  21.                 mLists[i]->outbufAcquireFenceFd = -1;  
  22.             } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  23.                 // garbage data to catch improper use  
  24.                 mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;  
  25.                 mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;  
  26.             } else {  
  27.                 mLists[i]->dpy = EGL_NO_DISPLAY;  
  28.                 mLists[i]->sur = EGL_NO_SURFACE;  
  29.             }  
  30.         }  
  31.     }  
  32.   
  33.     int err = mHwc->prepare(mHwc, mNumDisplays, mLists);//调用hwc的prepare函数  
  34.   
  35.     if (err == NO_ERROR) {  
  36.         for (size_t i=0 ; i<mNumDisplays ; i++) {  
  37.             DisplayData& disp(mDisplayData[i]);  
  38.             disp.hasFbComp = false;  
  39.             disp.hasOvComp = false;  
  40.             if (disp.list) {  
  41.                 for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {  
  42.                     hwc_layer_1_t& l = disp.list->hwLayers[i];//遍历各个layer,设置disp的各个变量  
  43.   
  44.                     if (l.flags & HWC_SKIP_LAYER) {  
  45.                         l.compositionType = HWC_FRAMEBUFFER;  
  46.                     }  
  47.                     if (l.compositionType == HWC_FRAMEBUFFER) {  
  48.                         disp.hasFbComp = true;  
  49.                     }  
  50.                     if (l.compositionType == HWC_OVERLAY) {  
  51.                         disp.hasOvComp = true;  
  52.                     }  
  53.                     if (l.compositionType == HWC_CURSOR_OVERLAY) {  
  54.                         disp.hasOvComp = true;  
  55.                     }  
  56.                 }  
  57.                 if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {  
  58.                     disp.hasFbComp = true;  
  59.                 }  
  60.             } else {  
  61.                 disp.hasFbComp = true;  
  62.             }  
  63.         }  
  64.     }  
  65.     return (status_t)err;  
  66. }  


egl合成

http://blog.youkuaiyun.com/kc58236582/article/details/52868973#t1博客中,我们分析过GPU合成各个layer的流程。我们直接从egl合成好数据好之后开始分析,就到FramebufferSurface的onFrameAvailable函数。这个函数直接调用了HWComposer的fbPost函数。

[cpp]  view plain  copy
  1. void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {  
  2.     sp<GraphicBuffer> buf;  
  3.     sp<Fence> acquireFence;  
  4.     status_t err = nextBuffer(buf, acquireFence);  
  5.     if (err != NO_ERROR) {  
  6.         ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",  
  7.                 strerror(-err), err);  
  8.         return;  
  9.     }  
  10.     err = mHwc.fbPost(mDisplayType, acquireFence, buf);  
  11.     if (err != NO_ERROR) {  
  12.         ALOGE("error posting framebuffer: %d", err);  
  13.     }  
  14. }  
fbPost函数我们这里是调用了setFramebufferTarget函数。

[cpp]  view plain  copy
  1. int HWComposer::fbPost(int32_t id,  
  2.         const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {  
  3.     if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  4.         return setFramebufferTarget(id, acquireFence, buffer);  
  5.     } else {  
  6.         acquireFence->waitForever("HWComposer::fbPost");  
  7.         return mFbDev->post(mFbDev, buffer->handle);  
  8.     }  
  9. }  

setFramebufferTarget函数主要是将Target的handle对象给Framework层的DisplayData的fbTargetHandle

[cpp]  view plain  copy
  1. status_t HWComposer::setFramebufferTarget(int32_t id,  
  2.         const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {  
  3.     if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {  
  4.         return BAD_INDEX;  
  5.     }  
  6.     DisplayData& disp(mDisplayData[id]);  
  7.     if (!disp.framebufferTarget) {  
  8.         // this should never happen, but apparently eglCreateWindowSurface()  
  9.         // triggers a Surface::queueBuffer()  on some  
  10.         // devices (!?) -- log and ignore.  
  11.         ALOGE("HWComposer: framebufferTarget is null");  
  12.         return NO_ERROR;  
  13.     }  
  14.   
  15.     int acquireFenceFd = -1;  
  16.     if (acquireFence->isValid()) {  
  17.         acquireFenceFd = acquireFence->dup();  
  18.     }  
  19.   
  20.     // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);  
  21.     disp.fbTargetHandle = buf->handle;//将target的buffer的handle给DisplayData的fbTargetHandle  
  22.     disp.framebufferTarget->handle = disp.fbTargetHandle;  
  23.     disp.framebufferTarget->acquireFenceFd = acquireFenceFd;  
  24.     return NO_ERROR;  
  25. }  


HWC输出到显示设备

最后在SurfaceFlinger的doComposition函数中会调用postFramebuffer函数,这个函数主要是调用了HWComposer的commit函数,就到HWC模块来最后到显示设备上。

[cpp]  view plain  copy
  1. status_t HWComposer::commit() {  
  2.     int err = NO_ERROR;  
  3.     if (mHwc) {  
  4.         if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  5.             // On version 1.0, the OpenGL ES target surface is communicated  
  6.             // by the (dpy, sur) fields and we are guaranteed to have only  
  7.             // a single display.  
  8.             mLists[0]->dpy = eglGetCurrentDisplay();  
  9.             mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);  
  10.         }  
  11.   
  12.         for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {//虚拟设备,需要outbuf和outbufAcquireFenceFd   
  13.             DisplayData& disp(mDisplayData[i]);  
  14.             if (disp.outbufHandle) {  
  15.                 mLists[i]->outbuf = disp.outbufHandle;  
  16.                 mLists[i]->outbufAcquireFenceFd =  
  17.                         disp.outbufAcquireFence->dup();  
  18.             }  
  19.         }  
  20.   
  21.         err = mHwc->set(mHwc, mNumDisplays, mLists);//调用HWC的set函数,输出到显示设备  
  22.   
  23.         for (size_t i=0 ; i<mNumDisplays ; i++) {  
  24.             DisplayData& disp(mDisplayData[i]);  
  25.             disp.lastDisplayFence = disp.lastRetireFence;  
  26.             disp.lastRetireFence = Fence::NO_FENCE;  
  27.             if (disp.list) {  
  28.                 if (disp.list->retireFenceFd != -1) {  
  29.                     disp.lastRetireFence = new Fence(disp.list->retireFenceFd);  
  30.                     disp.list->retireFenceFd = -1;  
  31.                 }  
  32.                 disp.list->flags &= ~HWC_GEOMETRY_CHANGED;  
  33.             }  
  34.         }  
  35.     }  
  36.     return (status_t)err;  
  37. }  
<think>好的,用户问的是关于UIS7870平台在Android 13上适配多屏显示的修改点。首先,我需要确认UIS7870是什么芯片,可能属于某家国产车规级SoC,常用于智能座舱系统。多屏显示在车载场景中很常见,比如中控屏、仪表盘、后排娱乐屏等,所以适配多屏显示是关键需求。 接下来,用户提到Android 13,所以需要了解Android 13在显示系统方面的更新,比如DisplayManager、SurfaceFlinger的变化,以及多屏支持的API是否有变动。可能涉及HDMI、DisplayPort或虚拟显示的输出配置。 然后,适配多屏通常涉及内核驱动、HAL层、SurfaceFlinger配置、WindowManager策略等。需要检查显示驱动是否支持多路输出,HAL层是否有必要的接口实现,比如hwcomposer的配置。Android 13可能引入了新的多屏管理特性,比如动态分辨率切换、热插拔处理的改进,或者对多独立显示的支持。 另外,多屏显示在车载环境下可能有特殊需求,比如不同屏幕的不同DPI、方向、安全区域等,需要确认DisplayPolicy和WindowManager如何管理不同屏幕的窗口。Android 13的窗口管理是否有新API或行为变化,比如对Activity嵌入(ActivityEmbedding)的支持,或者分屏多任务的改进,这些都可能影响多屏适配。 还要考虑权限和安全方面,Android 13加强了隐私保护,多屏显示是否需要新的权限,比如投射内容到副屏是否需要用户授权。同时,系统服务如DisplayService是否需要调整,以确保多屏的生命周期管理正确。 可能还需要修改框架层的配置,比如config.xml中关于多屏的配置项,或者叠加层(overlay)的资源调整,比如分辨率和布局适应不同屏幕。另外,测试多屏时的性能优化,比如GPU渲染多路输出的性能,是否启用硬件加速合成等。 最后,参考Android官方文档中关于多屏支持的更新,以及芯片厂商(如UIS7870的供应商)提供的BSP更新,是否有针对Android 13的驱动或框架层补丁需要应用。可能需要查阅相关平台的开发文档或社区讨论,寻找适配案例。 总结步骤:1. 确认内核驱动支持多输出;2. 更新HAL层实现;3. 调整SurfaceFlinger和WindowManager配置;4. 处理热插拔和动态配置变更;5. 适配新的Android 13 API和安全策略;6. 测试和优化多屏性能及用户体验。</think>针对UIS7870车规级芯片在Android 13上适配多屏显示的关键修改点,以下是系统级的适配路径和技术细节: ### 一、显示子系统驱动层 1. **内核DRM/KMS驱动适配** - 需扩展`drm_driver`实现多CRTC/Encoder/Connector支持 - 配置`dts`文件定义多路显示管线: ```dts display-subsystem { ports = <&vop_out0>, <&vop_out1>; route { route_hdmi: route-hdmi { connect = <&vop_out0_hdmi>; }; route_lvds: route-lvds { connect = <&vop_out1_lvds>; }; } }; ``` - 实现`drm_panel`驱动对第二/第三屏幕的EDID解析 2. **GPU合成优化** - 启用`AFBC`(Arm Frame Buffer Compression)减少带宽占用 - 配置`MALI_GPU`分时复用策略: ```c mali_gpu_data.split_rsc_mgmt = MALI_SPLIT_RSC_MGMT_ENABLED; ``` ### 二、HAL层适配 1. **HWComposer 2.x扩展** - 实现`HWC2::Layer`的多显示上下文分离 - 配置`hwc_display_contents_1`结构体数组: ```cpp hwc_display_contents_1_t* displays[HWC_NUM_DISPLAY_TYPES]; displays[HWC_DISPLAY_PRIMARY] = &primary_display; displays[HWC_DISPLAY_EXTERNAL] = &ext_display; ``` 2. **Gralloc内存分配策略** - 针对不同屏幕设置`GRALLOC_USAGE`标志: ```cpp const uint64_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_TEXTURE | (is_secondary ? GRALLOC_USAGE_EXTERNAL_DISP : 0); ``` ### 三、Framework层修改 1. **DisplayManagerService增强** - 重写`LogicalDisplayMapper`处理动态显示拓扑: ```java public void configureLocked(int changes) { if ((changes & WindowManagerPolicy.DISPLAY_CHANGED_TOPOLOGY) != 0) { reconfigureDisplayLocked(); } } ``` 2. **WindowManager策略** - 在`DisplayPolicy.java`中定义多屏窗口策略: ```java void configureSecondaryDisplay(DisplayContent display) { display.getDisplayInfo().type = Display.TYPE_EXTERNAL; display.getDisplayRotation().setOrientation(DisplayInfo.ROTATION_90); } ``` 3. **SurfaceFlinger多显示合成** - 启用`MultiDisplayComposition`模式: ```cpp sp<DisplayDevice> dispDev = new DisplayDevice( surfaceFlinger, displayType, hwcDisplayId, ... ); surfaceFlinger->mDisplays.add(dispDev); ``` ### 四、Android 13新特性适配 1. **Display切换策略文件** - 新增`config_multipleDisplaySupport`资源配置: ```xml <!-- res/values/config.xml --> <bool name="config_supportsMultiDisplay">true</bool> <integer name="config_maxNumberOfDisplays">3</integer> ``` 2. **动态刷新率适配** - 实现`DisplayModeDirector`多显示实例: ```java for (Display display : displayManager.getDisplays()) { DisplayModeDirector director = new DisplayModeDirector( display.getDisplayId(), ... ); } ``` ### 五、车规级特殊需求 1. **ASIL-B安全显示** - 在`SurfaceControl`中设置安全层级: ```cpp surface->setLayer(SECURE_LAYER_BASE + displayId); surface->setSecure(true); ``` 2. **QoS带宽保障** - 配置显示带宽分配策略: ```shell echo "display0:4000 display1:2000" > /sys/class/devfreq/dmc/qos ``` 该适配方案需配合UIS7870的BSP包进行验证,重点测试多屏异源信号输出(如主屏2560x1600@60Hz + 副屏1920x720@120Hz)下的图形稳定性。建议使用Android 13新增的`dumpsys display`命令进行拓扑分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值