C++程序  |  225行  |  7.33 KB

/*
 * Copyright (C) 2017 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 "GrallocWrapper"

#include "GrallocWrapper.h"

#include <utils/Log.h>

namespace android {

GrallocWrapper::GrallocWrapper() {
    init();
}

void GrallocWrapper::init() {
    mAllocator = allocator2::IAllocator::getService();
    if (mAllocator == nullptr) {
        ALOGE("Failed to get allocator service");
    }

    mMapper = mapper2::IMapper::getService();
    if (mMapper == nullptr) {
        ALOGE("Failed to get mapper service");
    }
    if (mMapper->isRemote()) {
        ALOGE("Mapper is not in passthrough mode");
    }
}

GrallocWrapper::~GrallocWrapper() {
    for (auto bufferHandle : mClonedBuffers) {
        auto buffer = const_cast<native_handle_t*>(bufferHandle);
        native_handle_close(buffer);
        native_handle_delete(buffer);
    }
    mClonedBuffers.clear();

    for (auto bufferHandle : mImportedBuffers) {
        auto buffer = const_cast<native_handle_t*>(bufferHandle);
        if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
            ALOGE("Failed to free buffer %p", buffer);
        }
    }
    mImportedBuffers.clear();
}

sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
    return mAllocator;
}

std::string GrallocWrapper::dumpDebugInfo() {
    std::string debugInfo;
    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });

    return debugInfo;
}

const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) {
    const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());

    if (bufferHandle) {
        mClonedBuffers.insert(bufferHandle);
    }
    return bufferHandle;
}

std::vector<const native_handle_t*> GrallocWrapper::allocate(
    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) {
    std::vector<const native_handle_t*> bufferHandles;
    bufferHandles.reserve(count);
    mAllocator->allocate(descriptor, count,
                         [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
                             if (mapper2::Error::NONE != tmpError) {
                                 ALOGE("Failed to allocate buffers");
                             }
                             if (count != tmpBuffers.size()) {
                                 ALOGE("Invalid buffer array");
                             }

                             for (uint32_t i = 0; i < count; i++) {
                                 if (import) {
                                     bufferHandles.push_back(importBuffer(tmpBuffers[i]));
                                 } else {
                                     bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
                                 }
                             }

                             if (outStride) {
                                 *outStride = tmpStride;
                             }
                         });

    return bufferHandles;
}

const native_handle_t* GrallocWrapper::allocate(
    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
    uint32_t* outStride) {
    mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
    auto buffers = allocate(descriptor, 1, import, outStride);
    return buffers[0];
}

sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
    return mMapper;
}

mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
    mapper2::BufferDescriptor descriptor;
    mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
        if (tmpError != mapper2::Error::NONE) {
            ALOGE("Failed to create descriptor");
        }
        descriptor = tmpDescriptor;
    });

    return descriptor;
}

const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) {
    const native_handle_t* bufferHandle = nullptr;
    mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
        if (tmpError != mapper2::Error::NONE) {
            ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
        }
        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
    });

    if (bufferHandle) {
        mImportedBuffers.insert(bufferHandle);
    }

    return bufferHandle;
}

void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);

    if (mImportedBuffers.erase(bufferHandle)) {
        mapper2::Error error = mMapper->freeBuffer(buffer);
        if (error != mapper2::Error::NONE) {
            ALOGE("Failed to free %p", buffer);
        }
    } else {
        mClonedBuffers.erase(bufferHandle);
        native_handle_close(buffer);
        native_handle_delete(buffer);
    }
}

void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
                           const mapper2::IMapper::Rect& accessRegion, int acquireFence) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);

    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
    hardware::hidl_handle acquireFenceHandle;
    if (acquireFence >= 0) {
        auto h = native_handle_init(acquireFenceStorage, 1, 0);
        h->data[0] = acquireFence;
        acquireFenceHandle = h;
    }

    void* data = nullptr;
    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
                  [&](const auto& tmpError, const auto& tmpData) {
                      if (tmpError != mapper2::Error::NONE) {
                          ALOGE("Failed to lock buffer %p", buffer);
                      }
                      data = tmpData;
                  });

    if (acquireFence >= 0) {
        close(acquireFence);
    }

    return data;
}

int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);

    int releaseFence = -1;
    mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
        if (tmpError != mapper2::Error::NONE) {
            ALOGE("Failed to unlock buffer %p", buffer);
        }

        auto fenceHandle = tmpReleaseFence.getNativeHandle();
        if (fenceHandle) {
            if (fenceHandle->numInts != 0) {
                ALOGE("Invalid fence handle %p", fenceHandle);
            }
            if (fenceHandle->numFds == 1) {
                releaseFence = dup(fenceHandle->data[0]);
                if (releaseFence < 0) {
                    ALOGE("Failed to dup fence fd");
                }
            } else {
                if (fenceHandle->numFds != 0) {
                    ALOGE("Invalid fence handle %p", fenceHandle);
                }
            }
        }
    });

    return releaseFence;
}

}  // namespace android