Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb03fd3a authored by Dan Stoza's avatar Dan Stoza
Browse files

libui: Add Gralloc1On0Adapter and C++ shim

Adds an adapter which provides the gralloc1 interface on top of a
gralloc 0.x device as well as a C++ shim which wraps a gralloc1 device
and provides a somewhat nicer interface to the rest of the system.

This has also been squashed with a later commit that added mutexes to
protect both the buffer list and the descriptor list from concurrent
access.

Bug: 28401203
Bug: 29420918
Change-Id: I0eeafc998b56e2e2fc39de6fad41e3ed2e19658a
parent 204240a8
Loading
Loading
Loading
Loading

include/ui/Gralloc1.h

0 → 100644
+238 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_UI_GRALLOC1_H
#define ANDROID_UI_GRALLOC1_H

#define GRALLOC1_LOG_TAG "Gralloc1"

#include <ui/Gralloc1On0Adapter.h>

#include <unordered_set>

namespace std {
    template <>
    struct hash<gralloc1_capability_t> {
        size_t operator()(gralloc1_capability_t capability) const {
            return std::hash<int32_t>()(static_cast<int32_t>(capability));
        }
    };
}

namespace android {

class Fence;
class GraphicBuffer;

namespace Gralloc1 {

class Device;

class Descriptor {
public:
    Descriptor(Device& device, gralloc1_buffer_descriptor_t deviceId)
      : mShimDevice(device),
        mDeviceId(deviceId),
        mWidth(0),
        mHeight(0),
        mFormat(static_cast<android_pixel_format_t>(0)),
        mProducerUsage(GRALLOC1_PRODUCER_USAGE_NONE),
        mConsumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {}

    ~Descriptor();

    gralloc1_buffer_descriptor_t getDeviceId() const { return mDeviceId; }

    gralloc1_error_t setDimensions(uint32_t width, uint32_t height);
    gralloc1_error_t setFormat(android_pixel_format_t format);
    gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage);
    gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage);

private:
    Device& mShimDevice;
    const gralloc1_buffer_descriptor_t mDeviceId;

    uint32_t mWidth;
    uint32_t mHeight;
    android_pixel_format_t mFormat;
    gralloc1_producer_usage_t mProducerUsage;
    gralloc1_consumer_usage_t mConsumerUsage;

}; // Descriptor

class Device {
    friend class Gralloc1::Descriptor;

public:
    Device(gralloc1_device_t* device);

    bool hasCapability(gralloc1_capability_t capability) const;

    std::string dump();

    std::shared_ptr<Descriptor> createDescriptor();

    gralloc1_error_t getStride(buffer_handle_t buffer, uint32_t* outStride);

    gralloc1_error_t allocate(
            const std::vector<std::shared_ptr<const Descriptor>>& descriptors,
            std::vector<buffer_handle_t>* outBuffers);
    gralloc1_error_t allocate(
            const std::shared_ptr<const Descriptor>& descriptor,
            gralloc1_backing_store_t id, buffer_handle_t* outBuffer);

    gralloc1_error_t retain(buffer_handle_t buffer);
    gralloc1_error_t retain(const GraphicBuffer* buffer);

    gralloc1_error_t release(buffer_handle_t buffer);

    gralloc1_error_t getNumFlexPlanes(buffer_handle_t buffer,
            uint32_t* outNumPlanes);

    gralloc1_error_t lock(buffer_handle_t buffer,
            gralloc1_producer_usage_t producerUsage,
            gralloc1_consumer_usage_t consumerUsage,
            const gralloc1_rect_t* accessRegion, void** outData,
            const sp<Fence>& acquireFence);
    gralloc1_error_t lockFlex(buffer_handle_t buffer,
            gralloc1_producer_usage_t producerUsage,
            gralloc1_consumer_usage_t consumerUsage,
            const gralloc1_rect_t* accessRegion,
            struct android_flex_layout* outData, const sp<Fence>& acquireFence);
    gralloc1_error_t lockYCbCr(buffer_handle_t buffer,
            gralloc1_producer_usage_t producerUsage,
            gralloc1_consumer_usage_t consumerUsage,
            const gralloc1_rect_t* accessRegion, struct android_ycbcr* outData,
            const sp<Fence>& acquireFence);

    gralloc1_error_t unlock(buffer_handle_t buffer, sp<Fence>* outFence);

private:
    std::unordered_set<gralloc1_capability_t> loadCapabilities();

    bool loadFunctions();

    template <typename LockType, typename OutType>
    gralloc1_error_t lockHelper(LockType pfn, buffer_handle_t buffer,
            gralloc1_producer_usage_t producerUsage,
            gralloc1_consumer_usage_t consumerUsage,
            const gralloc1_rect_t* accessRegion, OutType* outData,
            const sp<Fence>& acquireFence) {
        int32_t intError = pfn(mDevice, buffer,
                static_cast<uint64_t>(producerUsage),
                static_cast<uint64_t>(consumerUsage), accessRegion, outData,
                acquireFence->dup());
        return static_cast<gralloc1_error_t>(intError);
    }

    gralloc1_device_t* const mDevice;

    const std::unordered_set<gralloc1_capability_t> mCapabilities;

    template <typename PFN, gralloc1_function_descriptor_t descriptor>
    struct FunctionLoader {
        FunctionLoader() : pfn(nullptr) {}

        bool load(gralloc1_device_t* device, bool errorIfNull) {
            gralloc1_function_pointer_t rawPointer =
                    device->getFunction(device, descriptor);
            pfn = reinterpret_cast<PFN>(rawPointer);
            if (errorIfNull && !rawPointer) {
                ALOG(LOG_ERROR, GRALLOC1_LOG_TAG,
                        "Failed to load function pointer %d", descriptor);
            }
            return rawPointer != nullptr;
        }

        template <typename ...Args>
        typename std::result_of<PFN(Args...)>::type operator()(Args... args) {
            return pfn(args...);
        }

        PFN pfn;
    };

    // Function pointers
    struct Functions {
        FunctionLoader<GRALLOC1_PFN_DUMP, GRALLOC1_FUNCTION_DUMP> dump;
        FunctionLoader<GRALLOC1_PFN_CREATE_DESCRIPTOR,
                GRALLOC1_FUNCTION_CREATE_DESCRIPTOR> createDescriptor;
        FunctionLoader<GRALLOC1_PFN_DESTROY_DESCRIPTOR,
                GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR> destroyDescriptor;
        FunctionLoader<GRALLOC1_PFN_SET_CONSUMER_USAGE,
                GRALLOC1_FUNCTION_SET_CONSUMER_USAGE> setConsumerUsage;
        FunctionLoader<GRALLOC1_PFN_SET_DIMENSIONS,
                GRALLOC1_FUNCTION_SET_DIMENSIONS> setDimensions;
        FunctionLoader<GRALLOC1_PFN_SET_FORMAT,
                GRALLOC1_FUNCTION_SET_FORMAT> setFormat;
        FunctionLoader<GRALLOC1_PFN_SET_PRODUCER_USAGE,
                GRALLOC1_FUNCTION_SET_PRODUCER_USAGE> setProducerUsage;
        FunctionLoader<GRALLOC1_PFN_GET_BACKING_STORE,
                GRALLOC1_FUNCTION_GET_BACKING_STORE> getBackingStore;
        FunctionLoader<GRALLOC1_PFN_GET_CONSUMER_USAGE,
                GRALLOC1_FUNCTION_GET_CONSUMER_USAGE> getConsumerUsage;
        FunctionLoader<GRALLOC1_PFN_GET_DIMENSIONS,
                GRALLOC1_FUNCTION_GET_DIMENSIONS> getDimensions;
        FunctionLoader<GRALLOC1_PFN_GET_FORMAT,
                GRALLOC1_FUNCTION_GET_FORMAT> getFormat;
        FunctionLoader<GRALLOC1_PFN_GET_PRODUCER_USAGE,
                GRALLOC1_FUNCTION_GET_PRODUCER_USAGE> getProducerUsage;
        FunctionLoader<GRALLOC1_PFN_GET_STRIDE,
                GRALLOC1_FUNCTION_GET_STRIDE> getStride;
        FunctionLoader<GRALLOC1_PFN_ALLOCATE,
                GRALLOC1_FUNCTION_ALLOCATE> allocate;
        FunctionLoader<GRALLOC1_PFN_RETAIN,
                GRALLOC1_FUNCTION_RETAIN> retain;
        FunctionLoader<GRALLOC1_PFN_RELEASE,
                GRALLOC1_FUNCTION_RELEASE> release;
        FunctionLoader<GRALLOC1_PFN_GET_NUM_FLEX_PLANES,
                GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES> getNumFlexPlanes;
        FunctionLoader<GRALLOC1_PFN_LOCK,
                GRALLOC1_FUNCTION_LOCK> lock;
        FunctionLoader<GRALLOC1_PFN_LOCK_FLEX,
                GRALLOC1_FUNCTION_LOCK_FLEX> lockFlex;
        FunctionLoader<GRALLOC1_PFN_LOCK_YCBCR,
                GRALLOC1_FUNCTION_LOCK_YCBCR> lockYCbCr;
        FunctionLoader<GRALLOC1_PFN_UNLOCK,
                GRALLOC1_FUNCTION_UNLOCK> unlock;

        // Adapter-only functions
        FunctionLoader<GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER,
                GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER> retainGraphicBuffer;
        FunctionLoader<GRALLOC1_PFN_ALLOCATE_WITH_ID,
                GRALLOC1_FUNCTION_ALLOCATE_WITH_ID> allocateWithId;
    } mFunctions;

}; // class android::Gralloc1::Device

class Loader
{
public:
    Loader();
    ~Loader();

    std::unique_ptr<Device> getDevice();

private:
    static std::unique_ptr<Gralloc1On0Adapter> mAdapter;
    std::unique_ptr<Device> mDevice;
};

} // namespace android::Gralloc1

} // namespace android

#endif
+481 −0

File added.

Preview size limit exceeded, changes collapsed.

+3 −1
Original line number Original line Diff line number Diff line
@@ -17,7 +17,7 @@ include $(CLEAR_VARS)


LOCAL_CLANG := true
LOCAL_CLANG := true
LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
LOCAL_SANITIZE := integer
# LOCAL_SANITIZE := integer


# The static constructors and destructors in this library have not been noted to
# The static constructors and destructors in this library have not been noted to
# introduce significant overheads
# introduce significant overheads
@@ -37,6 +37,8 @@ LOCAL_CPPFLAGS += -Wno-padded
LOCAL_SRC_FILES := \
LOCAL_SRC_FILES := \
	Fence.cpp \
	Fence.cpp \
	FrameStats.cpp \
	FrameStats.cpp \
	Gralloc1.cpp \
	Gralloc1On0Adapter.cpp \
	GraphicBuffer.cpp \
	GraphicBuffer.cpp \
	GraphicBufferAllocator.cpp \
	GraphicBufferAllocator.cpp \
	GraphicBufferMapper.cpp \
	GraphicBufferMapper.cpp \

libs/ui/Gralloc1.cpp

0 → 100644
+402 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0

#include <ui/Gralloc1.h>

#include <vector>

#undef LOG_TAG
#define LOG_TAG GRALLOC1_LOG_TAG

namespace android {

namespace Gralloc1 {

Descriptor::~Descriptor()
{
    int32_t intError = mShimDevice.mFunctions.destroyDescriptor(
            mShimDevice.mDevice, mDeviceId);
    auto error = static_cast<gralloc1_error_t>(intError);
    if (error != GRALLOC1_ERROR_NONE) {
        ALOGE("destroyDescriptor failed: %d", intError);
    }
}

gralloc1_error_t Descriptor::setDimensions(uint32_t width, uint32_t height)
{
    int32_t intError = mShimDevice.mFunctions.setDimensions(mShimDevice.mDevice,
            mDeviceId, width, height);
    auto error = static_cast<gralloc1_error_t>(intError);
    if (error != GRALLOC1_ERROR_NONE) {
        return error;
    }
    mWidth = width;
    mHeight = height;
    return error;
}

template <typename ApiType>
struct Setter {
    typedef int32_t (*Type)(gralloc1_device_t*, gralloc1_buffer_descriptor_t,
            ApiType);
};

template <typename ApiType, typename ValueType>
static inline gralloc1_error_t setHelper(
        typename Setter<ApiType>::Type setter, gralloc1_device_t* device,
        gralloc1_buffer_descriptor_t id, ValueType newValue,
        ValueType* cacheVariable)
{
    int32_t intError = setter(device, id, static_cast<ApiType>(newValue));
    auto error = static_cast<gralloc1_error_t>(intError);
    if (error != GRALLOC1_ERROR_NONE) {
        return error;
    }
    *cacheVariable = newValue;
    return error;
}

gralloc1_error_t Descriptor::setFormat(android_pixel_format_t format)
{
    return setHelper<int32_t>(mShimDevice.mFunctions.setFormat.pfn,
            mShimDevice.mDevice, mDeviceId, format, &mFormat);
}

gralloc1_error_t Descriptor::setProducerUsage(gralloc1_producer_usage_t usage)
{
    return setHelper<uint64_t>(mShimDevice.mFunctions.setProducerUsage.pfn,
            mShimDevice.mDevice, mDeviceId, usage, &mProducerUsage);
}

gralloc1_error_t Descriptor::setConsumerUsage(gralloc1_consumer_usage_t usage)
{
    return setHelper<uint64_t>(mShimDevice.mFunctions.setConsumerUsage.pfn,
            mShimDevice.mDevice, mDeviceId, usage, &mConsumerUsage);
}

Device::Device(gralloc1_device_t* device)
  : mDevice(device),
    mCapabilities(loadCapabilities()),
    mFunctions()
{
    if (!loadFunctions()) {
        ALOGE("Failed to load a required function, aborting");
        abort();
    }
}

bool Device::hasCapability(gralloc1_capability_t capability) const
{
    return mCapabilities.count(capability) > 0;
}

std::string Device::dump()
{
    uint32_t length = 0;
    mFunctions.dump(mDevice, &length, nullptr);

    std::vector<char> output;
    output.resize(length);
    mFunctions.dump(mDevice, &length, output.data());

    return std::string(output.cbegin(), output.cend());
}

std::shared_ptr<Descriptor> Device::createDescriptor()
{
    gralloc1_buffer_descriptor_t descriptorId;
    int32_t intError = mFunctions.createDescriptor(mDevice, &descriptorId);
    auto error = static_cast<gralloc1_error_t>(intError);
    if (error != GRALLOC1_ERROR_NONE) {
        return nullptr;
    }
    auto descriptor = std::make_shared<Descriptor>(*this, descriptorId);
    return descriptor;
}

gralloc1_error_t Device::getStride(buffer_handle_t buffer, uint32_t* outStride)
{
    int32_t intError = mFunctions.getStride(mDevice, buffer, outStride);
    return static_cast<gralloc1_error_t>(intError);
}

static inline bool allocationSucceded(gralloc1_error_t error)
{
    return error == GRALLOC1_ERROR_NONE || error == GRALLOC1_ERROR_NOT_SHARED;
}

gralloc1_error_t Device::allocate(
        const std::vector<std::shared_ptr<const Descriptor>>& descriptors,
        std::vector<buffer_handle_t>* outBuffers)
{
    if (mFunctions.allocate.pfn == nullptr) {
        // Allocation is not supported on this device
        return GRALLOC1_ERROR_UNSUPPORTED;
    }

    std::vector<gralloc1_buffer_descriptor_t> deviceIds;
    for (const auto& descriptor : descriptors) {
        deviceIds.emplace_back(descriptor->getDeviceId());
    }

    std::vector<buffer_handle_t> buffers(descriptors.size());
    int32_t intError = mFunctions.allocate(mDevice,
            static_cast<uint32_t>(descriptors.size()), deviceIds.data(),
            buffers.data());
    auto error = static_cast<gralloc1_error_t>(intError);
    if (allocationSucceded(error)) {
        *outBuffers = std::move(buffers);
    }

    return error;
}

gralloc1_error_t Device::allocate(
        const std::shared_ptr<const Descriptor>& descriptor,
        gralloc1_backing_store_t id, buffer_handle_t* outBuffer)
{
    gralloc1_error_t error = GRALLOC1_ERROR_NONE;

    if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
        buffer_handle_t buffer = nullptr;
        int32_t intError = mFunctions.allocateWithId(mDevice,
                descriptor->getDeviceId(), id, &buffer);
        error = static_cast<gralloc1_error_t>(intError);
        if (allocationSucceded(error)) {
            *outBuffer = buffer;
        }
    } else {
        std::vector<std::shared_ptr<const Descriptor>> descriptors;
        descriptors.emplace_back(descriptor);
        std::vector<buffer_handle_t> buffers;
        error = allocate(descriptors, &buffers);
        if (allocationSucceded(error)) {
            *outBuffer = buffers[0];
        }
    }

    return error;
}

gralloc1_error_t Device::retain(buffer_handle_t buffer)
{
    int32_t intError = mFunctions.retain(mDevice, buffer);
    return static_cast<gralloc1_error_t>(intError);
}

gralloc1_error_t Device::retain(const GraphicBuffer* buffer)
{
    if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
        return mFunctions.retainGraphicBuffer(mDevice, buffer);
    } else {
        return retain(buffer->getNativeBuffer()->handle);
    }
}

gralloc1_error_t Device::release(buffer_handle_t buffer)
{
    int32_t intError = mFunctions.release(mDevice, buffer);
    return static_cast<gralloc1_error_t>(intError);
}

gralloc1_error_t Device::getNumFlexPlanes(buffer_handle_t buffer,
        uint32_t* outNumPlanes)
{
    uint32_t numPlanes = 0;
    int32_t intError = mFunctions.getNumFlexPlanes(mDevice, buffer, &numPlanes);
    auto error = static_cast<gralloc1_error_t>(intError);
    if (error == GRALLOC1_ERROR_NONE) {
        *outNumPlanes = numPlanes;
    }
    return error;
}

gralloc1_error_t Device::lock(buffer_handle_t buffer,
        gralloc1_producer_usage_t producerUsage,
        gralloc1_consumer_usage_t consumerUsage,
        const gralloc1_rect_t* accessRegion, void** outData,
        const sp<Fence>& acquireFence)
{
    ALOGV("Calling lock(%p)", buffer);
    return lockHelper(mFunctions.lock.pfn, buffer, producerUsage,
            consumerUsage, accessRegion, outData, acquireFence);
}

gralloc1_error_t Device::lockFlex(buffer_handle_t buffer,
        gralloc1_producer_usage_t producerUsage,
        gralloc1_consumer_usage_t consumerUsage,
        const gralloc1_rect_t* accessRegion,
        struct android_flex_layout* outData,
        const sp<Fence>& acquireFence)
{
    ALOGV("Calling lockFlex(%p)", buffer);
    return lockHelper(mFunctions.lockFlex.pfn, buffer, producerUsage,
            consumerUsage, accessRegion, outData, acquireFence);
}

gralloc1_error_t Device::lockYCbCr(buffer_handle_t buffer,
        gralloc1_producer_usage_t producerUsage,
        gralloc1_consumer_usage_t consumerUsage,
        const gralloc1_rect_t* accessRegion,
        struct android_ycbcr* outData,
        const sp<Fence>& acquireFence)
{
    ALOGV("Calling lockYCbCr(%p)", buffer);
    return lockHelper(mFunctions.lockYCbCr.pfn, buffer, producerUsage,
            consumerUsage, accessRegion, outData, acquireFence);
}

gralloc1_error_t Device::unlock(buffer_handle_t buffer, sp<Fence>* outFence)
{
    int32_t fenceFd = -1;
    int32_t intError = mFunctions.unlock(mDevice, buffer, &fenceFd);
    auto error = static_cast<gralloc1_error_t>(intError);
    if (error == GRALLOC1_ERROR_NONE) {
        *outFence = new Fence(fenceFd);
    }
    return error;
}

std::unordered_set<gralloc1_capability_t> Device::loadCapabilities()
{
    std::vector<int32_t> intCapabilities;
    uint32_t numCapabilities = 0;
    mDevice->getCapabilities(mDevice, &numCapabilities, nullptr);

    intCapabilities.resize(numCapabilities);
    mDevice->getCapabilities(mDevice, &numCapabilities, intCapabilities.data());

    std::unordered_set<gralloc1_capability_t> capabilities;
    for (const auto intCapability : intCapabilities) {
        capabilities.emplace(static_cast<gralloc1_capability_t>(intCapability));
    }
    return capabilities;
}

bool Device::loadFunctions()
{
    // Functions which must always be present
    if (!mFunctions.dump.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.createDescriptor.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.destroyDescriptor.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.setConsumerUsage.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.setDimensions.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.setFormat.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.setProducerUsage.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getBackingStore.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getConsumerUsage.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getDimensions.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getFormat.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getProducerUsage.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getStride.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.retain.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.release.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.getNumFlexPlanes.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.lock.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.lockFlex.load(mDevice, true)) {
        return false;
    }
    if (!mFunctions.unlock.load(mDevice, true)) {
        return false;
    }

    if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
        // These should always be present on the adapter
        if (!mFunctions.retainGraphicBuffer.load(mDevice, true)) {
            return false;
        }
        if (!mFunctions.lockYCbCr.load(mDevice, true)) {
            return false;
        }

        // allocateWithId may not be present if we're only able to map in this
        // process
        mFunctions.allocateWithId.load(mDevice, false);
    } else {
        // allocate may not be present if we're only able to map in this process
        mFunctions.allocate.load(mDevice, false);
    }

    return true;
}

std::unique_ptr<Gralloc1On0Adapter> Loader::mAdapter = nullptr;

Loader::Loader()
  : mDevice(nullptr)
{
    hw_module_t const* module;
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    uint8_t majorVersion = (module->module_api_version >> 8) & 0xFF;
    uint8_t minorVersion = module->module_api_version & 0xFF;
    gralloc1_device_t* device = nullptr;
    if (majorVersion == 1) {
        gralloc1_open(module, &device);
    } else {
        if (!mAdapter) {
            mAdapter = std::make_unique<Gralloc1On0Adapter>(module);
        }
        device = mAdapter->getDevice();
    }
    mDevice = std::make_unique<Gralloc1::Device>(device);
}

Loader::~Loader() {}

std::unique_ptr<Device> Loader::getDevice()
{
    return std::move(mDevice);
}

} // namespace android::Gralloc1

} // namespace android
+478 −0

File added.

Preview size limit exceeded, changes collapsed.