C++程序  |  524行  |  18.21 KB

/*
 * Copyright (C) 2008 The Android Open Source Project
 * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
 *
 * 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <limits.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>

#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>

#include <cutils/log.h>
#include <cutils/atomic.h>
#include <utils/Trace.h>

#include <hardware/hardware.h>
#include <hardware/gralloc.h>

#include "gralloc_priv.h"
#include "gr.h"
#include "alloc_controller.h"
#include "memalloc.h"
#include <qdMetaData.h>


using namespace gralloc;
/*****************************************************************************/

// Return the type of allocator -
// these are used for mapping/unmapping
static IMemAlloc* getAllocator(int flags)
{
    IMemAlloc* memalloc;
    IAllocController* alloc_ctrl = IAllocController::getInstance();
    memalloc = alloc_ctrl->getAllocator(flags);
    return memalloc;
}

static int gralloc_map_metadata(buffer_handle_t handle) {
    private_handle_t* hnd = (private_handle_t*)handle;
    hnd->base_metadata = 0;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    void *mappedAddress = MAP_FAILED;
    unsigned int size = 0;
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
        mappedAddress = MAP_FAILED;
        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        int ret = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset_metadata, hnd->fd_metadata);
        if(ret || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
                  hnd, hnd->fd_metadata, strerror(errno));
            return -errno;
        }
        hnd->base_metadata = uint64_t(mappedAddress);
    }
    return 0;
}

static int gralloc_map(gralloc_module_t const* module,
                       buffer_handle_t handle)
{
    ATRACE_CALL();
    if(!module)
        return -EINVAL;

    private_handle_t* hnd = (private_handle_t*)handle;
    unsigned int size = 0;
    int err = 0;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    void *mappedAddress = MAP_FAILED;
    hnd->base = 0;

    // Dont map framebuffer and secure buffers
    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
        size = hnd->size;
        err = memalloc->map_buffer(&mappedAddress, size,
                                       hnd->offset, hnd->fd);
        if(err || mappedAddress == MAP_FAILED) {
            ALOGE("Could not mmap handle %p, fd=%d (%s)",
                  handle, hnd->fd, strerror(errno));
            return -errno;
        }

        hnd->base = uint64_t(mappedAddress);
    } else {
        // Cannot map secure buffers or framebuffers, but still need to map
        // metadata for secure buffers.
        // If mapping a secure buffers fails, the framework needs to get
        // an error code.
        err = -EACCES;
    }

    //Allow mapping of metadata for all buffers including secure ones, but not
    //of framebuffer
    int metadata_err = gralloc_map_metadata(handle);
    if (!err) {
        err = metadata_err;
    }
    return err;
}

static int gralloc_unmap(gralloc_module_t const* module,
                         buffer_handle_t handle)
{
    ATRACE_CALL();
    int err = -EINVAL;
    if(!module)
        return err;

    private_handle_t* hnd = (private_handle_t*)handle;
    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
    if(!memalloc)
        return err;

    if(hnd->base) {
        err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
        if (err) {
            ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
                    strerror(errno));
            return -errno;
        }
        hnd->base = 0;
    }

    if(hnd->base_metadata) {
        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
        err = memalloc->unmap_buffer((void*)hnd->base_metadata,
                size, hnd->offset_metadata);
        if (err) {
            ALOGE("Could not unmap memory at address %p, %s",
                    (void*) hnd->base_metadata, strerror(errno));
            return -errno;
        }
        hnd->base_metadata = 0;
    }

    return 0;
}

/*****************************************************************************/

static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;

/*****************************************************************************/

int gralloc_register_buffer(gralloc_module_t const* module,
                            buffer_handle_t handle)
{
    ATRACE_CALL();
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err =  gralloc_map(module, handle);
    /* Do not fail register_buffer for secure buffers*/
    if (err == -EACCES)
        err = 0;
    return err;
}

int gralloc_unregister_buffer(gralloc_module_t const* module,
                              buffer_handle_t handle)
{
    ATRACE_CALL();
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    /*
     * If the buffer has been mapped during a lock operation, it's time
     * to un-map it. It's an error to be here with a locked buffer.
     * NOTE: the framebuffer is handled differently and is never unmapped.
     * Also base and base_metadata are reset.
     */
    return gralloc_unmap(module, handle);
}

int terminateBuffer(gralloc_module_t const* module,
                    private_handle_t* hnd)
{
    ATRACE_CALL();
    if(!module)
        return -EINVAL;

    /*
     * If the buffer has been mapped during a lock operation, it's time
     * to un-map it. It's an error to be here with a locked buffer.
     * NOTE: the framebuffer is handled differently and is never unmapped.
     * Also base and base_metadata are reset.
     */
    return gralloc_unmap(module, hnd);
}

static int gralloc_map_and_invalidate (gralloc_module_t const* module,
                                       buffer_handle_t handle, int usage)
{
    ATRACE_CALL();
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;
    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
        if (hnd->base == 0) {
            // we need to map for real
            pthread_mutex_t* const lock = &sMapLock;
            pthread_mutex_lock(lock);
            err = gralloc_map(module, handle);
            pthread_mutex_unlock(lock);
        }
        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
                hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
            //Invalidate if CPU reads in software and there are non-CPU
            //writers. No need to do this for the metadata buffer as it is
            //only read/written in software.
            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
                    (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
            {
                IMemAlloc* memalloc = getAllocator(hnd->flags) ;
                err = memalloc->clean_buffer((void*)hnd->base,
                        hnd->size, hnd->offset, hnd->fd,
                        CACHE_INVALIDATE);
            }
            //Mark the buffer to be flushed after CPU write.
            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
            }
        }
    }

    return err;
}

int gralloc_lock(gralloc_module_t const* module,
                 buffer_handle_t handle, int usage,
                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
                 void** vaddr)
{
    ATRACE_CALL();
    private_handle_t* hnd = (private_handle_t*)handle;
    int err = gralloc_map_and_invalidate(module, handle, usage);
    if(!err)
        *vaddr = (void*)hnd->base;
    return err;
}

int gralloc_lock_ycbcr(gralloc_module_t const* module,
                 buffer_handle_t handle, int usage,
                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
                 struct android_ycbcr *ycbcr)
{
    ATRACE_CALL();
    private_handle_t* hnd = (private_handle_t*)handle;
    int err = gralloc_map_and_invalidate(module, handle, usage);
    if(!err)
        err = getYUVPlaneInfo(hnd, ycbcr);
    return err;
}

int gralloc_unlock(gralloc_module_t const* module,
                   buffer_handle_t handle)
{
    ATRACE_CALL();
    if (!module || private_handle_t::validate(handle) < 0)
        return -EINVAL;

    int err = 0;
    private_handle_t* hnd = (private_handle_t*)handle;

    IMemAlloc* memalloc = getAllocator(hnd->flags);
    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
        err = memalloc->clean_buffer((void*)hnd->base,
                hnd->size, hnd->offset, hnd->fd,
                CACHE_CLEAN);
        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
    }

    return err;
}

/*****************************************************************************/

int gralloc_perform(struct gralloc_module_t const* module,
                    int operation, ... )
{
    int res = -EINVAL;
    va_list args;
    if(!module)
        return res;

    va_start(args, operation);
    switch (operation) {
        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
            {
                int fd = va_arg(args, int);
                unsigned int size = va_arg(args, unsigned int);
                unsigned int offset = va_arg(args, unsigned int);
                void* base = va_arg(args, void*);
                int width = va_arg(args, int);
                int height = va_arg(args, int);
                int format = va_arg(args, int);
                int alignedw = 0, alignedh = 0;

                native_handle_t** handle = va_arg(args, native_handle_t**);
                private_handle_t* hnd = (private_handle_t*)native_handle_create(
                    private_handle_t::sNumFds, private_handle_t::sNumInts());
                if (hnd) {
                  hnd->magic = private_handle_t::sMagic;
                  hnd->fd = fd;
                  hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
                  hnd->size = size;
                  hnd->offset = offset;
                  hnd->base = uint64_t(base) + offset;
                  hnd->gpuaddr = 0;
                  AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
                          height, format, 0, alignedw, alignedh);
                  hnd->width = alignedw;
                  hnd->height = alignedh;
                  hnd->unaligned_width = width;
                  hnd->unaligned_height = height;
                  hnd->format = format;
                  *handle = (native_handle_t *)hnd;
                  res = 0;
                }
                break;

            }
        case GRALLOC_MODULE_PERFORM_GET_STRIDE:
            {
                int width   = va_arg(args, int);
                int format  = va_arg(args, int);
                int *stride = va_arg(args, int *);
                int alignedw = 0, alignedh = 0;
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
                        0, format, 0, alignedw, alignedh);
                *stride = alignedw;
                res = 0;
            } break;

        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
            {
                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *stride = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }

                int alignedw = 0, alignedh = 0;
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
                *stride = alignedw;

                res = 0;
            } break;

        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
            {
                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *stride = va_arg(args, int *);
                int *height = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }

                int alignedw = 0, alignedh = 0;
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
                *stride = alignedw;
                *height = alignedh;

                res = 0;
            } break;

        case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
            {
                int width   = va_arg(args, int);
                int height  = va_arg(args, int);
                int format  = va_arg(args, int);
                int usage   = va_arg(args, int);
                int *alignedWidth = va_arg(args, int *);
                int *alignedHeight = va_arg(args, int *);
                int *tileEnabled = va_arg(args,int *);
                *tileEnabled = isUBwcEnabled(format, usage);
                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
                        height, format, usage, *alignedWidth, *alignedHeight);
                res = 0;
            } break;

        case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *color_space = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                if (!metadata) {
                    break;
#ifdef USE_COLOR_METADATA
                } else if (metadata->operation & COLOR_METADATA) {
                    ColorMetaData *colorMetadata = &metadata->color;
                    res = 0;
                    switch (colorMetadata->colorPrimaries) {
                    case ColorPrimaries_BT709_5:
                        *color_space = HAL_CSC_ITU_R_709;
                        break;
                    case ColorPrimaries_BT601_6_525:
                        *color_space = ((colorMetadata->range) ?
                                        HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
                        break;
                    case ColorPrimaries_BT2020:
                        *color_space = (colorMetadata->range) ?
                            HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
                        break;
                    default:
                        res = -EINVAL;
                        break;
                    }
#endif
                } else if(metadata->operation & UPDATE_COLOR_SPACE) {
                    *color_space = metadata->colorSpace;
                    res = 0;
                }
            } break;

        case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
                if (!private_handle_t::validate(hnd)) {
                    res = getYUVPlaneInfo(hnd, ycbcr);
                }
            } break;

        case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *map_secure_buffer = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
                    *map_secure_buffer = metadata->mapSecureBuffer;
                    res = 0;
                } else {
                    *map_secure_buffer = 0;
                }
            } break;

        case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                int *flag = va_arg(args, int *);
                if (private_handle_t::validate(hnd)) {
                    return res;
                }
                *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                if (metadata && (metadata->operation & LINEAR_FORMAT)) {
                    *flag = 0;
                }
                res = 0;
            } break;

        case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
            {
                private_handle_t* hnd = va_arg(args, private_handle_t*);
                void** rgb_data = va_arg(args, void**);
                if (!private_handle_t::validate(hnd)) {
                    res = getRgbDataAddress(hnd, rgb_data);
                }
            } break;

        case GRALLOC_MODULE_PERFORM_GET_IGC:
            {
                private_handle_t* hnd = va_arg(args, private_handle_t*);
                uint32_t *igc = va_arg(args, uint32_t *);
                if (!private_handle_t::validate(hnd) && igc) {
                    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
                    if (metadata && (metadata->operation & SET_IGC)) {
                        *igc = metadata->igc;
                        res = 0;
                    }
                }
            } break;

        case GRALLOC_MODULE_PERFORM_SET_IGC:
            res = 0;
            break;

        case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
            {
                private_handle_t* hnd =  va_arg(args, private_handle_t*);
                uint32_t *enable = va_arg(args, uint32_t*);
                if (!private_handle_t::validate(hnd)) {
                    setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
                    res = 0;
                }
            } break;
        default:
            break;
    }
    va_end(args);
    return res;
}