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

Commit 1e00defb authored by Chia-I Wu's avatar Chia-I Wu Committed by Android (Google) Code Review
Browse files

Merge changes from topic 'gralloc-hal'

* changes:
  graphics: add a default implementation to IMapper
  graphics: add IMapper to complement IAllocator
  graphics: add a default implementation to IAllocator
  Add HAL definition for graphics buffer allocator
parents 7ff7da90 0f215c5a
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -3,6 +3,10 @@ subdirs = [
    "audio/common/2.0",
    "audio/common/2.0",
    "audio/effect/2.0",
    "audio/effect/2.0",
    "benchmarks/msgq/1.0",
    "benchmarks/msgq/1.0",
    "graphics/allocator/2.0",
    "graphics/allocator/2.0/default",
    "graphics/mapper/2.0",
    "graphics/mapper/2.0/default",
    "memtrack/1.0",
    "memtrack/1.0",
    "memtrack/1.0/default",
    "memtrack/1.0/default",
    "light/2.0",
    "light/2.0",
+46 −0
Original line number Original line Diff line number Diff line
// This file is autogenerated by hidl-gen. Do not edit manually.

genrule {
    name: "android.hardware.graphics.allocator@2.0_genc++",
    tool: "hidl-gen",
    cmd: "$tool -o $genDir -Lc++ -randroid.hardware:hardware/interfaces android.hardware.graphics.allocator@2.0",
    srcs: [
        "types.hal",
        "IAllocator.hal",
    ],
    out: [
        "android/hardware/graphics/allocator/2.0/types.cpp",
        "android/hardware/graphics/allocator/2.0/AllocatorAll.cpp",
    ],
}

genrule {
    name: "android.hardware.graphics.allocator@2.0_genc++_headers",
    tool: "hidl-gen",
    cmd: "$tool -o $genDir -Lc++ -randroid.hardware:hardware/interfaces android.hardware.graphics.allocator@2.0",
    srcs: [
        "types.hal",
        "IAllocator.hal",
    ],
    out: [
        "android/hardware/graphics/allocator/2.0/types.h",
        "android/hardware/graphics/allocator/2.0/IAllocator.h",
        "android/hardware/graphics/allocator/2.0/IHwAllocator.h",
        "android/hardware/graphics/allocator/2.0/BnAllocator.h",
        "android/hardware/graphics/allocator/2.0/BpAllocator.h",
        "android/hardware/graphics/allocator/2.0/BsAllocator.h",
    ],
}

cc_library_shared {
    name: "android.hardware.graphics.allocator@2.0",
    generated_sources: ["android.hardware.graphics.allocator@2.0_genc++"],
    generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
    export_generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
    shared_libs: [
        "libhidl",
        "libhwbinder",
        "libutils",
        "libcutils",
    ],
}
+177 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 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.
 */

package android.hardware.graphics.allocator@2.0;

interface IAllocator {
    enum Capability : int32_t {
        /* reserved */
        INVALID = 0,

        /*
         * testAllocate will always return UNDEFINED unless this capability
         * is supported.
         */
        TEST_ALLOCATE = 1,
    };

    struct BufferDescriptorInfo {
        /*
         * The width specifies how many columns of pixels should be in the
         * allocated buffer, but does not necessarily represent the offset in
         * columns between the same column in adjacent rows. The rows may be
         * padded.
         */
        uint32_t width;

       /*
        * The height specifies how many rows of pixels should be in the
        * allocated buffer.
        */
        uint32_t height;

        /* Buffer pixel format. */
        PixelFormat format;

        /*
         * Buffer producer usage mask; valid flags can be found in the
         * definition of ProducerUsage.
         */
        uint64_t producerUsageMask;

        /*
         * Buffer consumer usage mask; valid flags can be found in the
         * definition of ConsumerUsage.
         */
        uint64_t consumerUsageMask;
    };

    /*
     * Provides a list of supported capabilities (as described in the
     * definition of Capability above). This list must not change after
     * initialization.
     *
     * @return capabilities is a list of supported capabilities.
     */
    getCapabilities() generates (vec<Capability> capabilities);

    /*
     * Retrieves implementation-defined debug information, which will be
     * displayed during, for example, `dumpsys SurfaceFlinger`.
     *
     * @return debugInfo is a string of debug information.
     */
    dumpDebugInfo() generates (string debugInfo);

    /*
     * Creates a new, opaque buffer descriptor.
     *
     * @param descriptorInfo specifies the attributes of the buffer
     *        descriptor.
     * @return error is NONE upon success. Otherwise,
     *         BAD_VALUE when any attribute in descriptorInfo is invalid.
     *         NO_RESOURCES when no more descriptors can currently be created.
     * @return descriptor is the newly created buffer descriptor.
     */
    createDescriptor(BufferDescriptorInfo descriptorInfo)
          generates (Error error,
                     BufferDescriptor descriptor);

    /*
     * Destroys an existing buffer descriptor.
     *
     * @param descriptor is the descriptor to destroy.
     * @return error is either NONE or BAD_DESCRIPTOR.
     */
    destroyDescriptor(BufferDescriptor descriptor) generates (Error error);

    /*
     * Tests whether a buffer allocation can succeed, ignoring potential
     * resource contention which might lead to a NO_RESOURCES error.
     *
     * @param descriptors is a list of buffer descriptors.
     * @return error is NONE or NOT_SHARED upon success;
     *         NONE when buffers can be created and share a backing store.
     *         NOT_SHARED when buffers can be created but require more than a
     *                    backing store.
     *         Otherwise,
     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
     *         UNSUPPORTED when any of the descriptors can never be satisfied.
     *         UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
     */
    testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);

    /*
     * Attempts to allocate a list of buffers sharing a backing store.
     *
     * Each buffer will correspond to one of the descriptors passed into the
     * function and will hold a reference to its backing store. If the device
     * is unable to share the backing store between the buffers, it must
     * attempt to allocate the buffers with different backing stores and
     * return NOT_SHARED if it is successful.
     *
     * @param descriptors is the buffer descriptors to attempt to allocate.
     * @return error is NONE or NOT_SHARED upon success;
     *         NONE when buffers can be created and share a backing store.
     *         NOT_SHARED when buffers can be created but require more than a
     *                    backing store.
     *         Otherwise,
     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
     *         UNSUPPORTED when any of the descriptors can never be satisfied.
     *         NO_RESOURCES when any of the buffers cannot be created at this
     *                      time.
     * @return buffers is the allocated buffers.
     */
    allocate(vec<BufferDescriptor> descriptors)
        generates (Error error,
                   vec<Buffer> buffers);

    /*
     * Frees a buffer.
     *
     * @param buffer is the buffer to be freed.
     * @return error is NONE upon success. Otherwise,
     *         BAD_BUFFER when the buffer is invalid.
     */
    free(Buffer buffer) generates (Error error);

    /*
     * Exports a buffer for use in other client libraries or for cross-process
     * sharing.
     *
     * The exported handle is a handle to the backing store of the buffer, not
     * to the buffer itself. It however may not hold any reference to the
     * backing store and may be considered invalid by client libraries. To use
     * it and, in most cases, to save it for later use, a client must make a
     * clone of the handle and have the cloned handle hold a reference to the
     * backing store. Such a cloned handle will stay valid even after the
     * original buffer is freed. Refer to native_handle_clone and IMapper for
     * how a handle is cloned and how a reference is added.
     *
     * @param descriptor is the descriptor used to allocate the buffer.
     * @param buffer is the buffer to be exported.
     * @return error is NONE upon success. Otherwise,
     *         BAD_DESCRIPTOR when the descriptor is invalid.
     *         BAD_BUFFER when the buffer is invalid.
     *         BAD_VALUE when descriptor and buffer do not match.
     *         NO_RESOURCES when the buffer cannot be exported at this time.
     * @return bufferHandle is the exported handle.
     */
    exportHandle(BufferDescriptor descriptor,
                 Buffer buffer)
      generates (Error error,
                 handle bufferHandle);
};
+24 −0
Original line number Original line 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 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_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
Loading