Android显示系统-GraphicBuffer和Gralloc分析

GraphicBuffer和Gralloc分析

BufferQueue中的Buffer对象,我们用的都是GraphicBuffer,那么GraphicBuffer是怎么来的呢?接下里我们具体来看这里的流程。

Surface是Andorid窗口的描述,是ANativeWindow的实现;同样GraphicBuffer是Android中图形Buffer的描述,是ANativeWindowBuffer的实现。而一个窗口,可以有几个Buffer。

GraphicBuffer定义

* frameworks/native/include/ui/GraphicBuffer.h

class GraphicBuffer
    : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
      public Flattenable<GraphicBuffer>
{
    friend class Flattenable<GraphicBuffer>;
public:

其中ANativeObjectBase是一个模板类,定义如下:

* frameworks/native/include/ui/ANativeObjectBase.h

template <typename NATIVE_TYPE, typename TYPE, typename REF,
        typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
public:
    // Disambiguate between the incStrong in REF and NATIVE_TYPE
    void incStrong(const void* id) const {
        REF::incStrong(id);
    }
    void decStrong(const void* id) const {
        REF::decStrong(id);
    }

这样ANativeObjectBase继承ANativeWindowBuffer和RefBase,GraphicBuffer继承ANativeObjectBase和Flattenable。

这样做的目的
RefBase使GraphicBuffer支持引用计数控制
Flattenable使GraphicBuffer支持序列化。 其中的关键类 ANativeWindowBuffer,它是一个结构体,是对Native Buffer的一个描述,其定义如下:

* frameworks/native/libs/nativebase/include/nativebase/nativebase.h

typedef struct ANativeWindowBuffer
{
#ifdef __cplusplus
    // 构造函数,decStrong和incStrong的实现;得初始化common
#endif

    struct android_native_base_t common;

    int width;
    int height;
    int stride;
    int format;
    int usage_deprecated;
    uintptr_t layerCount;

    void* reserved[1];

    const native_handle_t* handle;
    uint64_t usage;

    void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
} ANativeWindowBuffer_t;

typedef struct ANativeWindowBuffer ANativeWindowBuffer;

// Old typedef for backwards compatibility.
typedef ANativeWindowBuffer_t android_native_buffer_t;

ANativeWindowBuffer中,很多属性前面我们介绍Surface时,已经介绍过了。这里重点看看这个native_handle_t。

* system/core/libcutils/include/cutils/native_handle.h

typedef struct native_handle
{
    int version;        /* sizeof(native_handle_t) */
    int numFds;         /* number of file-descriptors at &data[0] */
    int numInts;        /* number of ints at &data[numFds] */
    ... ...
    int data[0];        /* numFds + numInts ints */
    ... ...
} native_handle_t;

typedef const native_handle_t* buffer_handle_t;

native_handle_t也就是具体Buffer的句柄,根据native_handle_t就能找到护体的Buffer。这里是用文件描述符进行描述的。

GraphicBuffer,很多属性都是继承于父类的,GraphicBuffer自己的属性比较少

 * frameworks/native/include/ui/GraphicBuffer.h

    uint8_t mOwner;

    ... ...

    GraphicBufferMapper& mBufferMapper;
    ssize_t mInitCheck;

    // numbers of fds/ints in native_handle_t to flatten
    uint32_t mTransportNumFds;
    uint32_t mTransportNumInts;

    uint64_t mId;

    // Stores the generation number of this buffer. If this number does not
    // match the BufferQueue's internal generation number (set through
    // IGBP::setGenerationNumber), attempts to attach the buffer will fail.
    uint32_t mGenerationNumber;
};
  • mOwner 表示该GraphicBuffer持有的只是handle,还是持有具体的数据
enum {
        ownNone   = 0,
        ownHandle = 1,
        ownData   = 2,
    };

mOwner不一样,释放时,流程不一样:

void GraphicBuffer::free_handle()
{
    if (mOwner == ownHandle) {
        mBufferMapper.freeBuffer(handle);
    } else if (mOwner == ownData) {
        GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
        allocator.free(handle);
    }
    handle = NULL;
}
  • GraphicBufferMapper GraphicBuffer实现Flattenable,可以将GraphicBuffer进行打包,在Binder中传递,但是传递只是Buffer的描述属性,并不真正去拷贝Buffer的内容。怎么实现的共享的,关键还是这里的handle。GraphicBufferMapper会根据handle去在不同的进程中进map,map到同一块物理内存。这里先埋个伏笔,后续我们会讲到。
  • mId GraphicBuffer的ID,这个ID在不同进程中都是一样的
  • mGenerationNumber 可以理解问题这个buffer被用多少次了。如果这个值和BufferQueue中的
  • mGenerationNumber不一直,那么是不能attach的。

余下,GraphicBuffer的相关函数我们接下来具体来看~

分配一块Buffer

Producer dequeueBuffer的时候,并不是 每一次都会去分配一块Buffer。还记得什么时候回去分配Buffer吗?没错,设置了标识BUFFER_NEEDS_REALLOCATION时。

if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                width, height, format, BQ_LAYER_COUNT, usage,
                {mConsumerName.string(), mConsumerName.size()});

此时分配的Buffer,参数比较齐全,对应的构造函数为:

* frameworks/native/libs/ui/GraphicBuffer.cpp

GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)
    : GraphicBuffer()
{
    mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
            usage, std::move(requestorName));
}

在默认构造函数中,主要是做变量是初始化:

GraphicBuffer::GraphicBuffer()
    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{
    width  =
    height =
    stride =
    format =
    usage_deprecated = 0;
    usage  = 0;
    layerCount = 0;
    handle = NULL;
}

mOwner默认是ownData。GraphicBufferMapper是一个单例类,mBufferMapper在每个进程中只有一个实际对象。inLayerCount为1,在BufferQueueProducer中是一个常量。

static constexpr uint32_t BQ_LAYER_COUNT = 1;
status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
        std::string requestorName)
{
    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
    uint32_t outStride = 0;
    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
            inUsage, &handle, &outStride, mId,
            std::move(requestorName));
    if (err == NO_ERROR) {
        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);

        width = static_cast<int>(inWidth);
        height = static_cast<int>(inHeight);
        format = inFormat;
        layerCount = inLayerCount;
        usage = inUsage;
        usage_deprecated = int(usage);
        stride = static_cast<int>(outStride);
    }
    return err;
}
  • GraphicBufferAllocator Buffer管理中,另外一个单例类,GraphicBufferAllocator把Buffer分配出来你,GraphicBufferMapper可以将其map到自己的进程。 需要主要的是,BufferQueueProducer是跑在SurfaceFlinger进程中的,也就是说,绝大部分的应用,使用的Buffer,都是SurfaceFlinger进程分配出来的,所以,如果SurfaceFlinger出现内存泄露,FD泄露等问题,很有可能都是应用没有释放,SurfaceFlinger不会主动释放,它只响应应用的请求。SurfaceFlinger是背锅侠!

GraphicBufferAllocator定义如下:

* frameworks/native/include/ui/GraphicBufferAllocator.h

class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
{
public:
    static inline GraphicBufferAllocator& get() { return getInstance(); }

    status_t allocate(uint32_t w, uint32_t h, PixelFormat format,
            uint32_t layerCount, uint64_t usage,
            buffer_handle_t* handle, uint32_t* stride, uint64_t graphicBufferId,
            std::string requestorName);

    status_t free(buffer_handle_t handle);

    void dump(String8& res) const;
    static void dumpToSystemLog();

private:
    struct alloc_rec_t {
        uint32_t width;
        uint32_t height;
        uint32_t stride;
        PixelFormat format;
        uint32_t layerCount;
        uint64_t usage;
        size_t size;
        std::string requestorName;
    };

    static Mutex sLock;
    static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;

    friend class Singleton<GraphicBufferAllocator>;
    GraphicBufferAllocator();
    ~GraphicBufferAllocator();

    GraphicBufferMapper& mMapper;
    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
};
  • 两个主要的方法,一个allocate用来分配Buffer,一个free用来释放Buffe。
  • sAllocList,申请的Buffer,都保存下来,放到sAllocList中,并不是保存具体的Buffer,而是Buffer的描述alloc_rec_t。
  • mAllocator,Gralloc登场,gralloc采用版本化管理,用的是Gralloc2。

GraphicBufferAllocator的allocate函数如下:

status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
        PixelFormat format, uint32_t layerCount, uint64_t usage,
        buffer_handle_t* handle, uint32_t* stride,
        uint64_t /*graphicBufferId*/, std::string requestorName)
{
    ATRACE_CALL();

    // make sure to not allocate a N x 0 or 0 x N buffer, since this is
    // allowed from an API stand-point allocate a 1x1 buffer instead.
    if (!width || !height)
        width = height = 1;

    // Ensure that layerCount is valid.
    if (layerCount < 1)
        layerCount = 1;

    Gralloc2::IMapper::BufferDescriptorInfo info = {};
    info.width = width;
    info.height = height;
    info.layerCount = layerCount;
    info.format = static_cast<Gralloc2::PixelFormat>(format);
    info.usage = usage;

    Gralloc2::Error error = mAllocator->allocate(info, stride, handle);
    if (error == Gralloc2::Error::NONE) {
        Mutex::Autolock _l(sLock);
        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
        uint32_t bpp = bytesPerPixel(format);
        alloc_rec_t rec;
        rec.width = width;
        rec.height = height;
        rec.stride = *stride;
        rec.format = format;
        rec.layerCount = layerCount;
        rec.usage = usage;
        rec.size = static_cast<size_t>(height * (*stride) * bpp);
        rec.requestorName = std::move(requestorName);
        list.add(*handle, rec);

        return NO_ERROR;
    } else {
        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
                "usage %" PRIx64 ": %d",
                width, height, layerCount, format, usage,
                error);
        return NO_MEMORY;
    }
}

在看allocate函数之前,我们先来看一下GraphicBuffer相关的类:
在这里插入图片描述GraphicBuffer的左膀右臂,GraphicBufferAllocator和GraphicBufferMapper!从Android 8.0开始,Android 操作系统框架在架构方面的一项重大改变,提出了treble 项目。Vendor的实现和Androd的实现分开,Android和HAL,采用HwBinder进行通信,减少Android对HAL的直接依赖。这里的Allocator和Mapper,就是对HAL结合的包装;IAllocator,IMapper的HAL的接口。V2_1::IMapper是一个对Gralloc HAL的2.1版本。

回到allocate函数~

BufferDescriptorInfo,对Buffer的描述,在HAL层也通用。根据需要,生成BufferDescriptorInfo,再通过Gralloc2的Allocator进行allocate。allocate出来的Buffer 句柄,保存在sAllocList中。

Gralloc2 Allocator的allocate函数提供了很多形态,可以满足我们不同的要求:

* frameworks/native/libs/ui/include/ui/Gralloc2.h

    /*
     * The returned buffers are already imported and must not be imported
     * again.  outBufferHandles must point to a space that can contain at
     * least "count" buffer_handle_t.
     */
    Error allocate(BufferDescriptor descriptor, uint32_t count,
            uint32_t* outStride, buffer_handle_t* outBufferHandles) const;

    Error allocate(BufferDescriptor descriptor,
            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
    {
        return allocate(descriptor, 1, outStride, outBufferHandle);
    }

    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t count,
            uint32_t* outStride, buffer_handle_t* outBufferHandles) const
    {
        BufferDescriptor descriptor;
        Error error = mMapper.createDescriptor(descriptorInfo, &descriptor);
        if (error == Error::NONE) {
            error = allocate(descriptor, count, outStride, outBufferHandles);
        }
        return error;
    }

    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
    {
        return allocate(descriptorInfo, 1, outStride, outBufferHandle);
    }

我们传的参数是BufferDescriptorInfo,首先要根据BufferDescriptorInfo,生成一个BufferDescriptor,这个是mapper的HAL层实现的,因为这个BufferDescriptor最后也是要给到HAL层,HAL层根据BufferDescriptor去生成相应描述的Buffer。

最后,allocate的通用实现如下:

* frameworks/native/libs/ui/Gralloc2.cpp

Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
        uint32_t* outStride, buffer_handle_t* outBufferHandles) const
{
    Error error;
    auto ret = mAllocator->allocate(descriptor, count,
            [&](const auto& tmpError, const auto& tmpStride,
                const auto& tmpBuffers) {
                error = tmpError;
                if (tmpError != Error::NONE) {
                    return;
                }

                // import buffers
                for (uint32_t i = 0; i < count; i++) {
                    error = mMapper.importBuffer(tmpBuffers[i],
                            &outBufferHandles[i]);
                    if (error != Error::NONE) {
                        for (uint32_t j = 0; j < i; j++) {
                            mMapper.freeBuffer(outBufferHandles[j]);
                            outBufferHandles[j] = nullptr;
                        }
                        return;
                    }
                }

                *outStride = tmpStride;
            });

    // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
    hardware::IPCThreadState::self()->flushCommands();

    return (ret.isOk()) ? error : kTransactionError;
}

count,表示需要分配的Buffer个数,也就是说我们一次可以分配多个Buffer。

allocator分配完成后,再通过importBuffer函数,import到我们的handle中outBufferHandle。

* frameworks/native/libs/ui/Gralloc2.cpp

Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
        buffer_handle_t* outBufferHandle) const
{
    Error error;
    auto ret = mMapper->importBuffer(rawHandle,
            [&](const auto& tmpError, const auto& tmpBuffer)
            {
                error = tmpError;
                if (error != Error::NONE) {
                    return;
                }

                *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
            });

    return (ret.isOk()) ? error : kTransactionError;
}

Gralloc1.0 接口介绍

Graphic相关的HAL的接口都在定义在hardware/interfaces/graphics/。allocator和mapper也是分开的。

IAllocator接口

* hardware/interfaces/graphics/allocator/2.0/IAllocator.hal

package android.hardware.graphics.allocator@2.0;

import android.hardware.graphics.mapper@2.0;

interface IAllocator {
    @entry
    @exit
    @callflow(next="*")
    dumpDebugInfo() generates (string debugInfo);

    @entry
    @exit
    @callflow(next="*")
    allocate(BufferDescriptor descriptor, uint32_t count)
        generates (Error error,
                   uint32_t stride,
                   vec<handle> buffers);
};

IAllocator主要两个接口:

  • allocate 根据Buffer Descriptor描述的属性,分配对应的Buffer;count,分配的个数;返回值,stride,Buffer 步长,何为步长?我们知道Buffer都有一个宽度,但是Buffer的内存中分配的时候,都是采用对齐后的大小。多少位对齐,每个硬件平台不一样。比如,我们在一个32对齐的平台上,需要申请一块60x60大小的Buffer。因为要做对齐,所以实际分配的大小为64x60。那么对于这块Buffer,stride就是64。这是因为我们读Buffer的时候,基本都是一行一行的读的,我们要读i行j列,也就是base + i*stride + j的位置。在有的场合下,高也会要求做对齐,那么60x60的Buffer,实际分配的大小是64x64的。buffers这是分配的Buffer的handle了。
  • dumpDebugInfo dump函数,主要用来debug用

所以,IAllocator的接口主要就一个allocate。

IAllocator又是怎么跟HAL模块连接上的呢?其实一个hidl的接口,在编译时会生成很多东西~

hidl_interface {
    name: "android.hardware.graphics.allocator@2.0",
    root: "android.hardware",
    vndk: {
        enabled: true,
    },
    srcs: [
        "IAllocator.hal",
    ],
    interfaces: [
        "android.hardware.graphics.common@1.0",
        "android.hardware.graphics.mapper@2.0",
        "android.hidl.base@1.0",
    ],
    gen_java: false,
}

IAllocator的目录如下:

out/soong/.intermediates/hardware/interfaces/graphics/allocator/2.0

./android.hardware.graphics.allocator@2.0_genc++_headers/gen/android/hardware/graphics/allocator/2.0/IAllocator.h
./android.hardware.graphics.allocator@2.0_genc++/gen/android/hardware/graphics/allocator/2.0/AllocatorAll.cpp

Gralloc2的构造函数中,将首先建立和HAL层的HwBinder服务连接

* frameworks/native/libs/ui/Gralloc2.cpp

Allocator::Allocator(const Mapper& mapper)
    : mMapper(mapper)
{
    mAllocator = IAllocator::getService();
    if (mAllocator == nullptr) {
        LOG_ALWAYS_FATAL("gralloc-alloc is missing");
    }
}

IAllocator的getService函数,是.hal文件中是没有定义的,但是编译的中间结果中会生成。

* out/soong/.intermediates/hardware/interfaces/graphics/allocator/2.0/android.hardware.graphics.allocator@2.0_genc++_headers/gen/android/hardware/graphics/allocator/2.0/IAllocator.h

static ::android::sp<IAllocator> getService(const std::string &serviceName="default", bool getStub=false);

这里用的是缺省构造函数,这里其实和Binder是类似的:

* out/soong/.intermediates/hardware/interfaces/graphics/allocator/2.0/android.hardware.graphics.allocator@2.0_genc++/gen/android/hardware/graphics/allocator/2.0/AllocatorAll.cpp

// static
::android::sp<IAllocator> IAllocator::getService(const std::string &serviceName, const bool getStub) {
    return ::android::hardware::details::getServiceInternal<BpHwAllocator>(serviceName, true, getStub);
}

注册的函数如下:

::android::status_t IAllocator::registerAsService(const std::string &serviceName) {
    ::android::hardware::details::onRegistration("android.hardware.graphics.allocator@2.0", "IAllocator", serviceName);

    const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm
            = ::android::hardware::defaultServiceManager();
    if (sm == nullptr) {
        return ::android::INVALID_OPERATION;
    }
    ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
    return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
}

IAllocator HAL服务是谁呢?默认的实现在这里:

hardware/interfaces/graphics/allocator/2.0/default

默认服务起来的时候,将通过defaultPassthroughServiceImplementation去注册IAllocator的HAL服务:

#define LOG_TAG "android.hardware.graphics.allocator@2.0-service"

#include <android/hardware/graphics/allocator/2.0/IAllocator.h>

#include <hidl/LegacySupport.h>

using android::hardware::graphics::allocator::V2_0::IAllocator;
using android::hardware::defaultPassthroughServiceImplementation;

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

defaultPassthroughServiceImplementation的实现在LegacySupport.h中

* system/libhidl/transport/include/hidl/LegacySupport.h

template<class Interface>
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(
        std::string name = "default") {
    sp<Interface> service = Interface::getService(name, true /* getStub */);

    if (service == nullptr) {
        ALOGE("Could not get passthrough implementation for %s/%s.",
            Interface::descriptor, name.c_str());
        return EXIT_FAILURE;
    }

    LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
            Interface::descriptor, name.c_str());

    status_t status = service->registerAsService(name);

    if (status == OK) {
        ALOGI("Registration complete for %s/%s.",
            Interface::descriptor, name.c_str());
    } else {
        ALOGE("Could not register service %s/%s (%d).",
            Interface::descriptor, name.c_str(), status);
    }

    return status;
}

template<class Interface>
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name,
                                            size_t maxThreads = 1) {
    configureRpcThreadpool(maxThreads, true);
    status_t result = registerPassthroughServiceImplementation<Interface>(name);

    if (result != OK) {
        return result;
    }

    joinRpcThreadpool();
    return UNKNOWN_ERROR;
}
template<class Interface>
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) {
    return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);
}

IAllocator被注册为Passthrough的Service。registerAsService,看看前面的函数,这个service将会被add到IServiceManager中,这这样,get的时候,就能获取到了。

获取到service的时,将会调HIDL_FETCH_***的函数,我们这里就是HIDL_FETCH_IAllocator,中间过程都是在system/libhidl中实现的。这里就不细跟了。

HIDL_FETCH_IAllocator的函数实现如下:

* hardware/interfaces/graphics/allocator/2.0/default/Gralloc.cpp

IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
    const hw_module_t* module = nullptr;
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    if (err) {
        ALOGE("failed to get gralloc module");
        return nullptr;
    }

    uint8_t major = (module->module_api_version >> 8) & 0xff;
    switch (major) {
        case 1:
            return new Gralloc1Allocator(module);
        case 0:
            return new Gralloc0Allocator(module);
        default:
            ALOGE("unknown gralloc module major version %d", major);
            return nullptr;
    }
}

HIDL_FETCH时,将会加载对应的HAL实现了。gralloc这边的HAL实现GRALLOC_HARDWARE_MODULE_ID。major就是gralloc的API版本。Gralloc1Allocator是对1.0版本的适配,Gralloc0Allocator是对最初版本的适配。

Gralloc1 Allocator HAL层接口 大多数Hardware的接口都定义在hardware/libhardware/include/hardware,Gralloc也不例外。

Gralloc1,HAL的描述为gralloc1_device_t

* hardware/libhardware/include/hardware/gralloc1.h

typedef struct gralloc1_device {
    /* Must be the first member of this struct, since a pointer to this struct
     * will be generated by casting from a hw_device_t* */
    struct hw_device_t common;

    // 获取Devices支持的能力
    void (*getCapabilities)(struct gralloc1_device* device, uint32_t* outCount,
            int32_t* /*gralloc1_capability_t*/ outCapabilities);

    // 获取对应功能的函数指针
    gralloc1_function_pointer_t (*getFunction)(struct gralloc1_device* device,
            int32_t /*gralloc1_function_descriptor_t*/ descriptor);
} gralloc1_device_t;

Gralloc1和前面的的实现有比较大的差别,接口都通过函数指针实现,不再采用原来的方式。

下面是Gralloc0的定义:

* hardware/libhardware/include/hardware/gralloc.h

typedef struct alloc_device_t {
    struct hw_device_t common;

    int (*alloc)(struct alloc_device_t* dev,
            int w, int h, int format, int usage,
            buffer_handle_t* handle, int* stride);

    int (*free)(struct alloc_device_t* dev,
            buffer_handle_t handle);

    void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);

    void* reserved_proc[7];
} alloc_device_t;

Gralloc0中,还是采用直接的函数调用。Gralloc1中,只是getCapabilities采用直接的函数调用。

Gralloc1时,走的Gralloc1Allocator,Gralloc0时,走的Gralloc0Allocator。我们主要来看一下Gralloc1Allocator。

* hardware/interfaces/graphics/allocator/2.0/default/Gralloc1Allocator.cpp

Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
    : mDevice(nullptr), mCapabilities(), mDispatch() {
    int result = gralloc1_open(module, &mDevice);
    if (result) {
        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
                         strerror(-result));
    }

    initCapabilities();
    initDispatch();
}

gralloc1_open,打开HAL层Gralloc1的具体实现。获取到gralloc1_device_t设备mDevice。

通过initCapabilities函数,将Gralloc1的能力都读出来,放到capabilities中

* hardware/interfaces/graphics/allocator/2.0/default/Gralloc1Allocator.cpp

void Gralloc1Allocator::initCapabilities() {
    uint32_t count = 0;
    mDevice->getCapabilities(mDevice, &count, nullptr);

    std::vector<int32_t> capabilities(count);
    mDevice->getCapabilities(mDevice, &count, capabilities.data());
    capabilities.resize(count);

    for (auto capability : capabilities) {
        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
            mCapabilities.layeredBuffers = true;
            break;
        }
    }
}

mDevice的getCapabilities函数调了两次,这个在HAL实现中经常用到,第一次,主要是获取大小,第二次才去获取具体的值。

initDispatch初始化函数指针,

* hardware/interfaces/graphics/allocator/2.0/default/Gralloc1Allocator.cpp

template <typename T>
void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
                                     T* outPfn) {
    auto pfn = mDevice->getFunction(mDevice, desc);
    if (!pfn) {
        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
    }

    *outPfn = reinterpret_cast<T>(pfn);
}

void Gralloc1Allocator::initDispatch() {
    initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
    initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
                 &mDispatch.createDescriptor);
    initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
                 &mDispatch.destroyDescriptor);
    initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
    initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
    if (mCapabilities.layeredBuffers) {
        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
                     &mDispatch.setLayerCount);
    }
    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
                 &mDispatch.setConsumerUsage);
    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
                 &mDispatch.setProducerUsage);
    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
}

mDevice根据gralloc1_function_descriptor_t,去HAL的实现中去获取对应的函数指针,初始化到mDispatch中。以后我们直接调mDispatch中的函数就访问到HAL的实现。

Gralloc1的gralloc1_function_descriptor_t包括:

* hardware/libhardware/include/hardware/gralloc1.h

typedef enum {
    GRALLOC1_FUNCTION_INVALID = 0,
    GRALLOC1_FUNCTION_DUMP = 1,
    GRALLOC1_FUNCTION_CREATE_DESCRIPTOR = 2,
    GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR = 3,
    GRALLOC1_FUNCTION_SET_CONSUMER_USAGE = 4,
    GRALLOC1_FUNCTION_SET_DIMENSIONS = 5,
    GRALLOC1_FUNCTION_SET_FORMAT = 6,
    GRALLOC1_FUNCTION_SET_PRODUCER_USAGE = 7,
    GRALLOC1_FUNCTION_GET_BACKING_STORE = 8,
    GRALLOC1_FUNCTION_GET_CONSUMER_USAGE = 9,
    GRALLOC1_FUNCTION_GET_DIMENSIONS = 10,
    GRALLOC1_FUNCTION_GET_FORMAT = 11,
    GRALLOC1_FUNCTION_GET_PRODUCER_USAGE = 12,
    GRALLOC1_FUNCTION_GET_STRIDE = 13,
    GRALLOC1_FUNCTION_ALLOCATE = 14,
    GRALLOC1_FUNCTION_RETAIN = 15,
    GRALLOC1_FUNCTION_RELEASE = 16,
    GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES = 17,
    GRALLOC1_FUNCTION_LOCK = 18,
    GRALLOC1_FUNCTION_LOCK_FLEX = 19,
    GRALLOC1_FUNCTION_UNLOCK = 20,
    GRALLOC1_FUNCTION_SET_LAYER_COUNT = 21,
    GRALLOC1_FUNCTION_GET_LAYER_COUNT = 22,
    GRALLOC1_LAST_FUNCTION = 22,
} gralloc1_function_descriptor_t;

IAllocator需要实现的gralloc1_function_descriptor_t包括:

* hardware/interfaces/graphics/allocator/2.0/default/Gralloc1Allocator.h
    struct {
        GRALLOC1_PFN_DUMP dump;
        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
        GRALLOC1_PFN_SET_FORMAT setFormat;
        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
        GRALLOC1_PFN_GET_STRIDE getStride;
        GRALLOC1_PFN_ALLOCATE allocate;
        GRALLOC1_PFN_RELEASE release;
    } mDispatch;

我们去实现Gralloc1的HAL时,allocator只去要实现getCapabilities和上面mDispatch中的gralloc1_function_descriptor_t就可以了。

https://zhuanlan.zhihu.com/p/253055674

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值