转自: http://blog.csdn.net/kc58236582/article/details/70146317
在之前的博客中,分析了SurfaceFlinger的流程,以及hwc和Gralloc模块的大致功能,但是对其中一些数据结构不是很清楚. 这篇博客我们主要从创建hwc_display_contents_1_t数据结构入手开始对hal层 hwc的一些数据结构进行分析。
我们先来看看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; }
在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; }
最后在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; }