显示HWC合成(hwc

xiaoxiao2021-02-28  62

转自: http://blog.csdn.net/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 ......   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<mDisplays.size() ; dpy++) {               sp<const DisplayDevice> hw(mDisplays[dpy]);               const int32_t id = hw->getHwcDisplayId();               if (id >= 0) {                   const Vector< sp<Layer> >& currentLayers(                       hw->getVisibleLayersSortedByZ());                   const size_t count = currentLayers.size();                   if (hwc.createWorkList(id, count) == NO_ERROR) {                       ......                   }               }           }       }   ......   status_t err = hwc.prepare();   ......  

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

[cpp]  view plain  copy struct DisplayData {       DisplayData();       ~DisplayData();       Vector<DisplayConfig> configs;       size_t currentConfig;       uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1       bool connected;       bool hasFbComp;       bool hasOvComp;       size_t capacity;       hwc_display_contents_1* list;//各个layer       hwc_layer_1* framebufferTarget;//gpu合成之后的layer       buffer_handle_t fbTargetHandle;       sp<Fence> lastRetireFence;  // signals when the last set op retires       sp<Fence> lastDisplayFence; // signals when the last set op takes                                   // effect on screen       buffer_handle_t outbufHandle;       sp<Fence> outbufAcquireFence;          // protected by mEventControlLock       int32_t events;   };  

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

[cpp]  view plain  copy status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {       if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {           return BAD_INDEX;       }          if (mHwc) {           DisplayData& disp(mDisplayData[id]);           if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {               // we need space for the HWC_FRAMEBUFFER_TARGET               numLayers++;           }           if (disp.capacity < numLayers || disp.list == NULL) {               size_t size = sizeof(hwc_display_contents_1_t)                       + numLayers * sizeof(hwc_layer_1_t);//申请内存的大小               free(disp.list);               disp.list = (hwc_display_contents_1_t*)malloc(size);//malloc内存               disp.capacity = numLayers;           }           if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {               disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];//list的hwLayers最后一个就是framebufferTarget               memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));               const DisplayConfig& currentConfig =                       disp.configs[disp.currentConfig];               const hwc_rect_t r = { 0, 0,                       (int) currentConfig.width, (int) currentConfig.height };               disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;//类型变成target的               disp.framebufferTarget->hints = 0;               disp.framebufferTarget->flags = 0;               disp.framebufferTarget->handle = disp.fbTargetHandle;               disp.framebufferTarget->transform = 0;               disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;               if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {                   disp.framebufferTarget->sourceCropf.left = 0;                   disp.framebufferTarget->sourceCropf.top = 0;                   disp.framebufferTarget->sourceCropf.right =                           currentConfig.width;                   disp.framebufferTarget->sourceCropf.bottom =                           currentConfig.height;               } else {                   disp.framebufferTarget->sourceCrop = r;               }               disp.framebufferTarget->displayFrame = r;               disp.framebufferTarget->visibleRegionScreen.numRects = 1;               disp.framebufferTarget->visibleRegionScreen.rects =                   &disp.framebufferTarget->displayFrame;               disp.framebufferTarget->acquireFenceFd = -1;               disp.framebufferTarget->releaseFenceFd = -1;               disp.framebufferTarget->planeAlpha = 0xFF;           }           disp.list->retireFenceFd = -1;           disp.list->flags = HWC_GEOMETRY_CHANGED;           disp.list->numHwLayers = numLayers;       }       return NO_ERROR;   }   hwc_display_contents_1的数据结构如下,代表的是一个设备的数据。

[cpp]  view plain  copy typedef struct hwc_display_contents_1 {       /* File descriptor referring to a Sync HAL fence object which will signal       * when this composition is retired. For a physical display, a composition       * is retired when it has been replaced on-screen by a subsequent set. For       * a virtual display, the composition is retired when the writes to       * outputBuffer are complete and can be read. The fence object is created       * and returned by the set call; this field will be -1 on entry to prepare       * and set. SurfaceFlinger will close the returned file descriptor.       */       int retireFenceFd;          union {           /* Fields only relevant for HWC_DEVICE_VERSION_1_0. */           struct {               /* (dpy, sur) is the target of SurfaceFlinger's OpenGL ES               * composition for HWC_DEVICE_VERSION_1_0. They aren't relevant to               * prepare. The set call should commit this surface atomically to               * the display along with any overlay layers.               */               hwc_display_t dpy;               hwc_surface_t sur;           };              /* These fields are used for virtual displays when the h/w composer           * version is at least HWC_DEVICE_VERSION_1_3. */           struct {               /* outbuf is the buffer that receives the composed image for               * virtual displays. Writes to the outbuf must wait until               * outbufAcquireFenceFd signals. A fence that will signal when               * writes to outbuf are complete should be returned in               * retireFenceFd.               *               * This field is set before prepare(), so properties of the buffer               * can be used to decide which layers can be handled by h/w               * composer.               *               * If prepare() sets all layers to FRAMEBUFFER, then GLES               * composition will happen directly to the output buffer. In this               * case, both outbuf and the FRAMEBUFFER_TARGET layer's buffer will               * be the same, and set() has no work to do besides managing fences.               *               * If the TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS board config               * variable is defined (not the default), then this behavior is               * changed: if all layers are marked for FRAMEBUFFER, GLES               * composition will take place to a scratch framebuffer, and               * h/w composer must copy it to the output buffer. This allows the               * h/w composer to do format conversion if there are cases where               * that is more desirable than doing it in the GLES driver or at the               * virtual display consumer.               *               * If some or all layers are marked OVERLAY, then the framebuffer               * and output buffer will be different. As with physical displays,               * the framebuffer handle will not change between frames if all               * layers are marked for OVERLAY.               */               buffer_handle_t outbuf;                  /* File descriptor for a fence that will signal when outbuf is               * ready to be written. The h/w composer is responsible for closing               * this when no longer needed.               *               * Will be -1 whenever outbuf is NULL, or when the outbuf can be               * written immediately.               */               int outbufAcquireFenceFd;           };       };          /* List of layers that will be composed on the display. The buffer handles       * in the list will be unique. If numHwLayers is 0, all composition will be       * performed by SurfaceFlinger.       */       uint32_t flags;       size_t numHwLayers;//layer的个数       hwc_layer_1_t hwLayers[0];//各个layer的起始指针      } hwc_display_contents_1_t;  

再来看看hwc_layer_1 的数据结构

[cpp]  view plain  copy typedef struct hwc_layer_1 {       /*       * compositionType is used to specify this layer's type and is set by either       * the hardware composer implementation, or by the caller (see below).       *       *  This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER       *  before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is       *  also set, otherwise, this field is preserved between (*prepare)()       *  calls.       *       * HWC_BACKGROUND       *   Always set by the caller before calling (*prepare)(), this value       *   indicates this is a special "background" layer. The only valid field       *   is backgroundColor.       *   The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT       *   handle the background color.       *       *       * HWC_FRAMEBUFFER_TARGET       *   Always set by the caller before calling (*prepare)(), this value       *   indicates this layer is the framebuffer surface used as the target of       *   OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY       *   or HWC_BACKGROUND, then no OpenGL ES composition will be done, and       *   this layer should be ignored during set().       *       *   This flag (and the framebuffer surface layer) will only be used if the       *   HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions,       *   the OpenGL ES target surface is communicated by the (dpy, sur) fields       *   in hwc_compositor_device_1_t.       *       *   This value cannot be set by the HWC implementation.       *       *       * HWC_FRAMEBUFFER       *   Set by the caller before calling (*prepare)() ONLY when the       *   HWC_GEOMETRY_CHANGED flag is also set.       *       *   Set by the HWC implementation during (*prepare)(), this indicates       *   that the layer will be drawn into the framebuffer using OpenGL ES.       *   The HWC can toggle this value to HWC_OVERLAY to indicate it will       *   handle the layer.       *       *       * HWC_OVERLAY       *   Set by the HWC implementation during (*prepare)(), this indicates       *   that the layer will be handled by the HWC (ie: it must not be       *   composited with OpenGL ES).       *       *       * HWC_SIDEBAND       *   Set by the caller before calling (*prepare)(), this value indicates       *   the contents of this layer come from a sideband video stream.       *       *   The h/w composer is responsible for receiving new image buffers from       *   the stream at the appropriate time (e.g. synchronized to a separate       *   audio stream), compositing them with the current contents of other       *   layers, and displaying the resulting image. This happens       *   independently of the normal prepare/set cycle. The prepare/set calls       *   only happen when other layers change, or when properties of the       *   sideband layer such as position or size change.       *       *   If the h/w composer can't handle the layer as a sideband stream for       *   some reason (e.g. unsupported scaling/blending/rotation, or too many       *   sideband layers) it can set compositionType to HWC_FRAMEBUFFER in       *   (*prepare)(). However, doing so will result in the layer being shown       *   as a solid color since the platform is not currently able to composite       *   sideband layers with the GPU. This may be improved in future       *   versions of the platform.       *       *       * HWC_CURSOR_OVERLAY       *   Set by the HWC implementation during (*prepare)(), this value       *   indicates the layer's composition will now be handled by the HWC.       *   Additionally, the client can now asynchronously update the on-screen       *   position of this layer using the setCursorPositionAsync() api.       */       int32_t compositionType;//注意上面注释          /*       * hints is bit mask set by the HWC implementation during (*prepare)().       * It is preserved between (*prepare)() calls, unless the       * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0.       *       * see hwc_layer_t::hints       */       uint32_t hints;          /* see hwc_layer_t::flags */       uint32_t flags;          union {           /* color of the background.  hwc_color_t.a is ignored */           hwc_color_t backgroundColor;              struct {               union {                   /* When compositionType is HWC_FRAMEBUFFER, HWC_OVERLAY,                   * HWC_FRAMEBUFFER_TARGET, this is the handle of the buffer to                   * compose. This handle is guaranteed to have been allocated                   * from gralloc using the GRALLOC_USAGE_HW_COMPOSER usage flag.                   * If the layer's handle is unchanged across two consecutive                   * prepare calls and the HWC_GEOMETRY_CHANGED flag is not set                   * for the second call then the HWComposer implementation may                   * assume that the contents of the buffer have not changed. */                   buffer_handle_t handle;//放数据的变量,下篇博客分析                      /* When compositionType is HWC_SIDEBAND, this is the handle                   * of the sideband video stream to compose. */                   const native_handle_t* sidebandStream;               };                  /* transformation to apply to the buffer during composition */               uint32_t transform;                  /* blending to apply during composition */               int32_t blending;                  ......                  /* where to composite the sourceCrop onto the display. The sourceCrop               * is scaled using linear filtering to the displayFrame. The origin is the               * top-left corner of the screen.               */               hwc_rect_t displayFrame;                  /* visible region in screen space. The origin is the               * top-left corner of the screen.               * The visible region INCLUDES areas overlapped by a translucent layer.               */               hwc_region_t visibleRegionScreen;                  /* Sync fence object that will be signaled when the buffer's               * contents are available. May be -1 if the contents are already               * available. This field is only valid during set(), and should be               * ignored during prepare(). The set() call must not wait for the               * fence to be signaled before returning, but the HWC must wait for               * all buffers to be signaled before reading from them.               *               * HWC_FRAMEBUFFER layers will never have an acquire fence, since               * reads from them are complete before the framebuffer is ready for               * display.               *               * HWC_SIDEBAND layers will never have an acquire fence, since               * synchronization is handled through implementation-defined               * sideband mechanisms.               *               * The HWC takes ownership of the acquireFenceFd and is responsible               * for closing it when no longer needed.               */               int acquireFenceFd;                  /* During set() the HWC must set this field to a file descriptor for               * a sync fence object that will signal after the HWC has finished               * reading from the buffer. The field is ignored by prepare(). Each               * layer should have a unique file descriptor, even if more than one               * refer to the same underlying fence object; this allows each to be               * closed independently.               *               * If buffer reads can complete at significantly different times,               * then using independent fences is preferred. For example, if the               * HWC handles some layers with a blit engine and others with               * overlays, then the blit layers can be reused immediately after               * the blit completes, but the overlay layers can't be reused until               * a subsequent frame has been displayed.               *               * Since HWC doesn't read from HWC_FRAMEBUFFER layers, it shouldn't               * produce a release fence for them. The releaseFenceFd will be -1               * for these layers when set() is called.               *               * Since HWC_SIDEBAND buffers don't pass through the HWC client,               * the HWC shouldn't produce a release fence for them. The               * releaseFenceFd will be -1 for these layers when set() is called.               *               * The HWC client taks ownership of the releaseFenceFd and is               * responsible for closing it when no longer needed.               */               int releaseFenceFd;                  ......                  /*               * Availability: HWC_DEVICE_API_VERSION_1_5               *               * This defines the region of the source buffer that has been               * modified since the last frame.               *               * If surfaceDamage.numRects > 0, then it may be assumed that any               * portion of the source buffer not covered by one of the rects has               * not been modified this frame. If surfaceDamage.numRects == 0,               * then the whole source buffer must be treated as if it had been               * modified.               *               * If the layer's contents are not modified relative to the prior               * prepare/set cycle, surfaceDamage will contain exactly one empty               * rect ([0, 0, 0, 0]).               *               * The damage rects are relative to the pre-transformed buffer, and               * their origin is the top-left corner.               */               hwc_region_t surfaceDamage;           };       };      ......      } 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 status_t HWComposer::prepare() {       Mutex::Autolock _l(mDisplayLock);       for (size_t i=0 ; i<mNumDisplays ; i++) {           DisplayData& disp(mDisplayData[i]);           if (disp.framebufferTarget) {               // make sure to reset the type to HWC_FRAMEBUFFER_TARGET               // DO NOT reset the handle field to NULL, because it's possible               // that we have nothing to redraw (eg: eglSwapBuffers() not called)               // in which case, we should continue to use the same buffer.               LOG_FATAL_IF(disp.list == NULL);               disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;//将framebufferTarget的类型赋值           }           if (!disp.connected && disp.list != NULL) {               ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",                     i, disp.list->numHwLayers);           }           mLists[i] = disp.list;//mLists中的数据就是对应各个显示设备的hwc_display_contents_1           if (mLists[i]) {               if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {                   mLists[i]->outbuf = disp.outbufHandle;                   mLists[i]->outbufAcquireFenceFd = -1;               } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {                   // garbage data to catch improper use                   mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;                   mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;               } else {                   mLists[i]->dpy = EGL_NO_DISPLAY;                   mLists[i]->sur = EGL_NO_SURFACE;               }           }       }          int err = mHwc->prepare(mHwc, mNumDisplays, mLists);//调用hwc的prepare函数          if (err == NO_ERROR) {           for (size_t i=0 ; i<mNumDisplays ; i++) {               DisplayData& disp(mDisplayData[i]);               disp.hasFbComp = false;               disp.hasOvComp = false;               if (disp.list) {                   for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {                       hwc_layer_1_t& l = disp.list->hwLayers[i];//遍历各个layer,设置disp的各个变量                          if (l.flags & HWC_SKIP_LAYER) {                           l.compositionType = HWC_FRAMEBUFFER;                       }                       if (l.compositionType == HWC_FRAMEBUFFER) {                           disp.hasFbComp = true;                       }                       if (l.compositionType == HWC_OVERLAY) {                           disp.hasOvComp = true;                       }                       if (l.compositionType == HWC_CURSOR_OVERLAY) {                           disp.hasOvComp = true;                       }                   }                   if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {                       disp.hasFbComp = true;                   }               } else {                   disp.hasFbComp = true;               }           }       }       return (status_t)err;   }  

egl合成

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

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

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

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

[cpp]  view plain  copy status_t HWComposer::setFramebufferTarget(int32_t id,           const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {       if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {           return BAD_INDEX;       }       DisplayData& disp(mDisplayData[id]);       if (!disp.framebufferTarget) {           // this should never happen, but apparently eglCreateWindowSurface()           // triggers a Surface::queueBuffer()  on some           // devices (!?) -- log and ignore.           ALOGE("HWComposer: framebufferTarget is null");           return NO_ERROR;       }          int acquireFenceFd = -1;       if (acquireFence->isValid()) {           acquireFenceFd = acquireFence->dup();       }          // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);       disp.fbTargetHandle = buf->handle;//将target的buffer的handle给DisplayData的fbTargetHandle       disp.framebufferTarget->handle = disp.fbTargetHandle;       disp.framebufferTarget->acquireFenceFd = acquireFenceFd;       return NO_ERROR;   }  

HWC输出到显示设备

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

[cpp]  view plain  copy status_t HWComposer::commit() {       int err = NO_ERROR;       if (mHwc) {           if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {               // On version 1.0, the OpenGL ES target surface is communicated               // by the (dpy, sur) fields and we are guaranteed to have only               // a single display.               mLists[0]->dpy = eglGetCurrentDisplay();               mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);           }              for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {//虚拟设备,需要outbuf和outbufAcquireFenceFd                DisplayData& disp(mDisplayData[i]);               if (disp.outbufHandle) {                   mLists[i]->outbuf = disp.outbufHandle;                   mLists[i]->outbufAcquireFenceFd =                           disp.outbufAcquireFence->dup();               }           }              err = mHwc->set(mHwc, mNumDisplays, mLists);//调用HWC的set函数,输出到显示设备              for (size_t i=0 ; i<mNumDisplays ; i++) {               DisplayData& disp(mDisplayData[i]);               disp.lastDisplayFence = disp.lastRetireFence;               disp.lastRetireFence = Fence::NO_FENCE;               if (disp.list) {                   if (disp.list->retireFenceFd != -1) {                       disp.lastRetireFence = new Fence(disp.list->retireFenceFd);                       disp.list->retireFenceFd = -1;                   }                   disp.list->flags &= ~HWC_GEOMETRY_CHANGED;               }           }       }       return (status_t)err;   }  
转载请注明原文地址: https://www.6miu.com/read-62866.html

最新回复(0)