joshuayingwhat IT Engineer

一:图形硬件(Gralloc,Hardware Composer)

2024-07-02

硬件抽象层统一了硬件调用的接口。

gralloc

图形缓冲,用于保存图形的一段内存。图形缓冲运行在一个独立的进程.由它负责分配图形缓冲。 是一个独立的进程。gralloc对应的接口类

interface IAllocator {
	allocate(BufferDescriptor descriptor, uint32_t count)
    generates (Error error,
               uint32_t stride,
               vec<handle> buffers);
};

其中BufferDescriptor描述了申请的buffer的宽高格式等信息。count表示申请的缓冲区的个数。 IAllocator 的具体实现在pasthrough.cpp

……

extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
    return GrallocLoader::load();
}

class GrallocLoader {
   public:
    static IAllocator* load() {
        const hw_module_t* module = loadModule();
        if (!module) {
            return nullptr;
        }
        auto hal = createHal(module);
        if (!hal) {
            return nullptr;
        }
        return createAllocator(std::move(hal));
    }

    // load the gralloc module
    static const hw_module_t* loadModule() {
        const hw_module_t* module;
        int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
        if (error) {
            ALOGE("failed to get gralloc module");
            return nullptr;
        }

        return module;
    }

    // create an AllocatorHal instance
    static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module) {
        int major = getModuleMajorApiVersion(module);
        switch (major) {
            case 1: {
                auto hal = std::make_unique<Gralloc1Hal>();
                return hal->initWithModule(module) ? std::move(hal) : nullptr;
            }
            case 0: {
                auto hal = std::make_unique<Gralloc0Hal>();
                return hal->initWithModule(module) ? std::move(hal) : nullptr;
            }
            default:
                ALOGE("unknown gralloc module major version %d", major);
                return nullptr;
        }
    }

    // create an IAllocator instance
    static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
        auto allocator = std::make_unique<hal::Allocator>();
        return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
    }
};

galloc 启动服务

int main() {
    return defaultPassthroughServiceImplementation<IAllocator>(4);
}

分配图形缓冲流程

客户端向galloc请求分配图形缓冲。

Allocator.allocate

AllocatorImpl.allocateBuffers

    Gralloc0HalImpl.allocateOneBuffer.alloc

        gralloc_context_t.gralloc_alloc

            gralloc.gralloc_alloc_buffer ![](https://s2.loli.net/2024/07/23/Q6vbWdmGKrxVpXE.png) 通过getserice获取gralloc的服务mallocator ![](https://s2.loli.net/2024/07/23/6JpfijhLGPYlgIn.png) 通过gralloc的代理服务mallocator调用allocate,向gralloc进程申请成功得到的缓冲通过outbufferhandles返回给调用者。

最终调用gralloc的gralloc_alloc_buffer分配内存缓冲 通过ashmem_create_region分配内存,最终将分配的内存的文件描述符以buffer_handle_t返回给客户端,客户端通过binder夸进程传输这个文件描述符,拿到文件描述符后就可以通过mmap操作得到缓冲地址。

图像缓冲

分配的图像缓冲内存以graphicbuffer表示.创建graphicbuffer阶段初始化就会调用 调用gralloc分配缓冲区内存,申请成功后缓冲保存到handle中,使用者得到graphicbuffer对象后取出地址才能保存图形数据。

status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
                                  int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
    const Rect lockBounds(width, height);
    status_t res =
            lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
    return res;
}

status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
                                  int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
    return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
}

status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
                                  const Rect& rect, void** vaddr, int fenceFd,
                                  int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
    auto result = getBufferMapper().lock(handle, usage, rect, base::unique_fd{fenceFd});

    if (!result.has_value()) {
        return result.error().asStatus();
    }
    auto value = result.value();
    *vaddr = value.address;

    if (outBytesPerPixel) {
        *outBytesPerPixel = legacyBpp != -1 ? legacyBpp : value.bytesPerPixel;
    }
    if (outBytesPerStride) {
        *outBytesPerStride = legacyBps != -1 ? legacyBps : value.bytesPerStride;
    }
    return OK;
}

graphicbuffer保存了图形缓冲的文件描述符handle,对文件描述符进行mmap操作可得到图形缓冲的内存地址。

应用程序调用graphicbuffer的lockasync可以获取缓冲的内存地址。应用程序得到地址后可以向图形缓冲读,写图形数据。

hardware composer

1.合成图形:把多个图形缓冲传给硬件混合渲染器,通知硬件混合渲染器执行合成操作。

2.显示图形:把图形缓冲直接显示到屏幕。

3.上报事件:接收底层上报的事件并转发给客户进程。 IComposer 主要用于客户端进程与hwc进程建立通信连接。

    /**
     * Creates a client of the composer. All resources created by the client
     * are owned by the client and are only visible to the client.
     *
     * There can only be one client at any time.
     *
     * @return error is NONE upon success. Otherwise,
     *         NO_RESOURCES when no more client can be created currently.
     * @return client is the newly created client.
     */
    @entry
    @callflow(next="*")
    createClient() generates (Error error, IComposerClient client);

createClient用于创建IComposerCliet对象,IComposer对象由HIDL_FETCH_ICoomposer创建

extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
    return GrallocLoader::load();
}
class HwcLoader {
   public:
    static IComposer* load() {
        const hw_module_t* module = loadModule();
        if (!module) {
            return nullptr;
        }
        auto hal = createHalWithAdapter(module);
        if (!hal) {
            return nullptr;
        }

        return createComposer(std::move(hal));
    }

加载模块;

创建适配层对象:hwchalimpl

创建IComposer对象:负责创建IComposerClient对象并返回给客户进程。 IComposerClient 每个客户对象对应一个屏幕

interface IComposerClient {
	@entry
    @callflow(next="*")
    registerCallback(IComposerCallback callback);
    @callflow(next="*")
    createLayer(Display display,
                uint32_t bufferSlotCount)
     generates (Error error,
                Layer layer);
}

注册回调,客户端可以接收hwc进程的事件。

interface IComposerCallback {
	  @callflow(next="*")
    onHotplug(Display display, Connection connected);
    @callflow(next="*")
    oneway onRefresh(Display display);
    @callflow(next="*")
    oneway onVsync(Display display, int64_t timestamp);
}

onHotplug:当前显示设备插入或者移除时,通知客户端进程

onrefresh:通知客户进程提供新的帧缓冲

onVsync:向客户进程发送Vsync信号

客户端进程通过composer与hwc进程通信

Composer {
	mComposer = IComposer.getservice(servicename);
	mComposer->createclient()
}

getservice得到IComposer对象。然后创建IComposerClinet对象保存到mClient中。

Composer通过mClinet与hwc进程建立通信连接。 硬件混合渲染器合成 客户进程需要把图形缓冲传给hwc进程,在由hwc进程传给显示驱动,通知硬件混合渲染器合成图像,合成好后直接传给显示设备。需要有3个步骤 1.创建图层 客户进程把图形缓冲传给hwc进程,首先需要创建涂层。 向hwc进程请求创建图层

ComposerClientImpl收到请求后转给适配层对象hwchalmpl处理。

hwchalimpl收到请求后交给设备对象处理。

hwcsession继承hwc2_device_t,收到createlayer后交给hwcdisplay处理 将创建的图层存放到layer_map中。 2.设置图层缓冲 设置好了图层后,客户端将图形缓冲传到hwc进程。composer的setlayerbuffer用于向hwc进程传递客户端进程的图形缓冲 其中取出graphicbuffer的handle。把handle传到hwc进程。

hwclayer处理setlayerbuffer

HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) {
  if (acquire_fence == 0) {
   DLOGE("acquire_fence is zero");
    return HWC2::Error::BadParameter;
 }
  const private_handle_t *handle = static_cast<const private_handle_t *>(buffer);
  layer_buffer->format = format;
  layer_buffer->width = UINT32(aligned_width);
  layer_buffer->height = UINT32(aligned_height);
  layer_buffer->unaligned_width = UINT32(handle->unaligned_width);
  layer_buffer->unaligned_height = UINT32(handle->unaligned_height);
  layer_buffer->planes[0].fd = ion_fd_;
  layer_buffer->planes[0].offset = handle->offset;
  layer_buffer->planes[0].stride = UINT32(handle->width);
  layer_buffer->acquire_fence_fd = acquire_fence;
  layer_buffer->size = handle->size;
  layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
  return HWC2::Error::None;
}

此时已经将图形缓冲的数据发送给了hwc 合成并显示 hwcdevice收到commit请求后把图层缓冲数据给到驱动。

DisplayError HWDevice::Commit(HWLayers *hw_layers) {
  DTRACE_SCOPED();
  HWLayersInfo &hw_layer_info = hw_layers->info;
  Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT)
  }

图形库合成 合成图形的工作也可以由客户端完成,客户端进程通过图形库合成图形的得到帧缓冲,通过hwc将帧缓冲传给显示驱动。 显示帧缓冲 hwc的hwc2onfbadapter收到请求后,调用framebuffer的fb_post将帧缓冲传递到显示驱动上 通过ioctl将帧缓冲传递到显示驱动,显示驱动收到帧缓冲会把它传给显示设备。


Similar Posts

下一篇 十:匿名binder

Content