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

Commit 109571a2 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

graphics: add a default implementation to IAllocator

The default implementatoin is built on top of conventional gralloc1.

This also adds a static library, libgralloc1-adapter.  It is intended to
ease the porting of gralloc0 to gralloc1.

Test: booted to launcher, tested with YouTube and some games.

Change-Id: Id640b1d5a1e1eea1aafabb6c134e6be6e71afff5
parent e78aa1bd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ subdirs = [
    "audio/effect/2.0",
    "benchmarks/msgq/1.0",
    "graphics/allocator/2.0",
    "graphics/allocator/2.0/default",
    "memtrack/1.0",
    "memtrack/1.0/default",
    "nfc/1.0",
+24 −0
Original line number Diff line number Diff line
cc_library_shared {
    name: "android.hardware.graphics.allocator@2.0-impl",
    relative_install_path: "hw",
    srcs: ["Gralloc.cpp"],
    cppflags: ["-Wall", "-Wextra"],
    shared_libs: [
        "android.hardware.graphics.allocator@2.0",
        "libbase",
        "libcutils",
        "libhardware",
        "libhidl",
        "libhwbinder",
        "liblog",
        "libutils",
    ],
}

cc_library_static {
    name: "libgralloc1-adapter",
    srcs: ["gralloc1-adapter.c"],
    include_dirs: ["system/core/libsync/include"],
    cflags: ["-Wall", "-Wextra", "-Wno-unused-parameter"],
    export_include_dirs: ["."],
}
+297 −0
Original line number 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_TAG "GrallocPassthrough"

#include <type_traits>
#include <unordered_set>
#include <vector>

#include <string.h>

#include <hardware/gralloc1.h>
#include <log/log.h>

#include "Gralloc.h"

namespace android {
namespace hardware {
namespace graphics {
namespace allocator {
namespace V2_0 {
namespace implementation {

class GrallocHal : public IAllocator {
public:
    GrallocHal(const hw_module_t* module);
    virtual ~GrallocHal();

    // IAllocator interface
    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
            createDescriptor_cb hidl_cb) override;
    Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;

    Return<Error> testAllocate(
            const hidl_vec<BufferDescriptor>& descriptors) override;
    Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
            allocate_cb hidl_cb) override;
    Return<Error> free(Buffer buffer) override;

    Return<void> exportHandle(BufferDescriptor descriptor,
            Buffer buffer, exportHandle_cb hidl_cb) override;

private:
    void initCapabilities();

    template<typename T>
    void initDispatch(T& func, gralloc1_function_descriptor_t desc);
    void initDispatch();

    bool hasCapability(Capability capability) const;

    gralloc1_device_t* mDevice;

    std::unordered_set<Capability> mCapabilities;

    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_CONSUMER_USAGE setConsumerUsage;
        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
        GRALLOC1_PFN_ALLOCATE allocate;
        GRALLOC1_PFN_RELEASE release;
        GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
        GRALLOC1_PFN_GET_STRIDE getStride;
        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
    } mDispatch;
};

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

    initCapabilities();
    initDispatch();
}

GrallocHal::~GrallocHal()
{
    gralloc1_close(mDevice);
}

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

    std::vector<Capability> caps(count);
    mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
              std::underlying_type<Capability>::type*>(caps.data()));
    caps.resize(count);

    mCapabilities.insert(caps.cbegin(), caps.cend());
}

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

    func = reinterpret_cast<T>(pfn);
}

void GrallocHal::initDispatch()
{
    initDispatch(mDispatch.dump, GRALLOC1_FUNCTION_DUMP);
    initDispatch(mDispatch.createDescriptor,
            GRALLOC1_FUNCTION_CREATE_DESCRIPTOR);
    initDispatch(mDispatch.destroyDescriptor,
            GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR);
    initDispatch(mDispatch.setDimensions, GRALLOC1_FUNCTION_SET_DIMENSIONS);
    initDispatch(mDispatch.setFormat, GRALLOC1_FUNCTION_SET_FORMAT);
    initDispatch(mDispatch.setConsumerUsage,
            GRALLOC1_FUNCTION_SET_CONSUMER_USAGE);
    initDispatch(mDispatch.setProducerUsage,
            GRALLOC1_FUNCTION_SET_PRODUCER_USAGE);
    initDispatch(mDispatch.allocate, GRALLOC1_FUNCTION_ALLOCATE);
    initDispatch(mDispatch.release, GRALLOC1_FUNCTION_RELEASE);
}

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

Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
{
    std::vector<Capability> caps(
            mCapabilities.cbegin(), mCapabilities.cend());

    hidl_vec<Capability> reply;
    reply.setToExternal(caps.data(), caps.size());
    hidl_cb(reply);

    return Void();
}

Return<void> GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
{
    uint32_t len = 0;
    mDispatch.dump(mDevice, &len, nullptr);

    std::vector<char> buf(len + 1);
    mDispatch.dump(mDevice, &len, buf.data());
    buf.resize(len + 1);
    buf[len] = '\0';

    hidl_string reply;
    reply.setToExternal(buf.data(), len);
    hidl_cb(reply);

    return Void();
}

Return<void> GrallocHal::createDescriptor(
        const BufferDescriptorInfo& descriptorInfo,
        createDescriptor_cb hidl_cb)
{
    BufferDescriptor descriptor;
    int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
    if (err == GRALLOC1_ERROR_NONE) {
        err = mDispatch.setDimensions(mDevice, descriptor,
                descriptorInfo.width, descriptorInfo.height);
    }
    if (err == GRALLOC1_ERROR_NONE) {
        err = mDispatch.setFormat(mDevice, descriptor,
                static_cast<int32_t>(descriptorInfo.format));
    }
    if (err == GRALLOC1_ERROR_NONE) {
        uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
        }
        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
        }
        err = mDispatch.setProducerUsage(mDevice, descriptor,
                descriptorInfo.producerUsageMask);
    }
    if (err == GRALLOC1_ERROR_NONE) {
        uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
        if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
            consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
        }
        err = mDispatch.setConsumerUsage(mDevice, descriptor,
                consumerUsageMask);
    }

    hidl_cb(static_cast<Error>(err), descriptor);

    return Void();
}

Return<Error> GrallocHal::destroyDescriptor(
        BufferDescriptor descriptor)
{
    int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
    return static_cast<Error>(err);
}

Return<Error> GrallocHal::testAllocate(
        const hidl_vec<BufferDescriptor>& descriptors)
{
    if (!hasCapability(Capability::TEST_ALLOCATE)) {
        return Error::UNDEFINED;
    }

    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
            &descriptors[0], nullptr);
    return static_cast<Error>(err);
}

Return<void> GrallocHal::allocate(
        const hidl_vec<BufferDescriptor>& descriptors,
        allocate_cb hidl_cb) {
    std::vector<buffer_handle_t> buffers(descriptors.size());
    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
            &descriptors[0], buffers.data());
    if (err != GRALLOC1_ERROR_NONE && err != GRALLOC1_ERROR_NOT_SHARED) {
        buffers.clear();
    }

    hidl_vec<Buffer> reply;
    reply.setToExternal(
            reinterpret_cast<Buffer*>(buffers.data()),
            buffers.size());
    hidl_cb(static_cast<Error>(err), reply);

    return Void();
}

Return<Error> GrallocHal::free(Buffer buffer)
{
    buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(buffer);
    int32_t err = mDispatch.release(mDevice, handle);
    return static_cast<Error>(err);
}

Return<void> GrallocHal::exportHandle(BufferDescriptor /*descriptor*/,
        Buffer buffer, exportHandle_cb hidl_cb)
{
    // do we want to validate?
    buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(buffer);

    hidl_cb(Error::NONE, handle);

    return Void();
}

IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
    const hw_module_t* module;
    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;
    if (major != 1) {
        ALOGE("unknown gralloc module major version %d", major);
        return nullptr;
    }

    return new GrallocHal(module);
}

} // namespace implementation
} // namespace V2_0
} // namespace allocator
} // namespace graphics
} // namespace hardware
} // namespace android
+38 −0
Original line number 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_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H

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

namespace android {
namespace hardware {
namespace graphics {
namespace allocator {
namespace V2_0 {
namespace implementation {

extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name);

} // namespace implementation
} // namespace V2_0
} // namespace allocator
} // namespace graphics
} // namespace hardware
} // namespace android

#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
+660 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading